En el tutorial anterior de esta serie, comenzamos a implementar el juego del juego y ya conseguimos que el avión se moviera por la pantalla. En este tutorial, continuaremos implementando el juego. Vamos a sumergirnos en el startTimers
función.
startTimers
Como su nombre lo indica, el startTimers
La función inicia los temporizadores. Agregue el siguiente código a gamelevel.lua.
función startTimers () end
Invoca esta función en el enterScene
método como se muestra a continuación.
escena de la función: enterScene (evento) local planeSound = audio.loadStream ("planesound.mp3") planeSoundChannel = audio.play (planeSound, loops = -1) Runtime: addEventListener ("enterFrame", gameLoop) startTimers () end
firePlayerBullet
los firePlayerBullet
La función crea una bala para el jugador..
function firePlayerBullet () local tempBullet = display.newImage ("bullet.png", (player.x + playerWidth / 2) - bulletWidth, player.y-bulletHeight) table.insert (playerBullets, tempBullet); planeGroup: insertar (tempBullet) final
Aquí utilizamos el objeto Display. nueva imagen
Método para crear la bala. Lo colocamos de tal manera que esté en el centro del plano en el eje x y en la parte superior del plano en el eje y. La bala se inserta en el jugadorBullets
mesa para referencia posterior y también en el grupo de aviones
.
firePlayerBullet
Necesitamos llamar al firePlayerBullet
funciona periódicamente para asegurarte de que el avión del jugador dispara balas automáticamente. Agregue el siguiente fragmento de código en el startTimers
función.
function startTimers () firePlayerBulletTimer = timer.performWithDelay (2000, firePlayerBullet, -1) end
Como su nombre lo indica, el temporizador realizar con demora
El método llama a una función específica después de un período de tiempo. El tiempo es en milisegundos, así que aquí estamos llamando al firePlayerBullet
Funciona cada dos segundos. Pasando -1
Como tercer argumento, el temporizador se repetirá para siempre..
Si prueba el juego ahora, debería ver que cada dos segundos aparece una bala. Sin embargo, todavía no se están moviendo. Nos encargaremos de eso en los próximos pasos..
movePlayerBullets
En movePlayerBullets
, recorremos el jugadorBullets
tabla y cambiar la y
coordenada de cada bala. Primero revisamos para asegurarnos de que el jugadorBullets
La mesa tiene balas en ella. los #
antes de jugadorBullets
se llama el longitud operador y devuelve la longitud del objeto al que se llama. Es útil saber que el #
operador también trabaja en cadenas.
función movePlayerBullets () si (#playerBullets> 0) entonces para i = 1, # playerBullets do playerBullets [i]. y = playerBullets [i] .y - 7 end end end end
Necesitamos invocar movePlayerBullets
en el gameLoop
funciona como se muestra a continuación.
function gameLoop () --SNIP-- numberOfTicks = numberOfTicks + 1 movePlayer () movePlayerBullets () end
checkPlayerBulletsOutOfBounds
Cuando una bala sale de la pantalla, ya no es relevante para el juego. Sin embargo, todavía son parte de la jugadorBullets
Tabla y continúe moviéndose como cualquier otra bala en la tabla. Esto es un desperdicio de recursos y, si el juego continuara por mucho tiempo, resultaría en cientos o miles de objetos no utilizados..
Para superar esto, monitoreamos las balas y, una vez que se mueven fuera de la pantalla, las eliminamos del jugadorBullets
mesa, así como a partir de la pantalla. Eche un vistazo a la implementación de checkPlayerBulletsOutOfBounds
.
function checkPlayerBulletsOutOfBounds () if (#playerBullets> 0) luego para i = # playerBullets, 1, -1 do if (playerBullets [i] .y < -18) then playerBullets[i]:removeSelf() playerBullets[i] = nil table.remove(playerBullets,i) end end end end
Es importante tener en cuenta que estamos recorriendo el jugadorBullets
Mesa al revés. Si recorramos la tabla hacia adelante, entonces, cuando eliminamos una de las viñetas, el índice de bucle se desactivará y se producirá un error. Al pasar por encima de la tabla en orden inverso, la última viñeta ya está procesada. los quitarse
El método elimina el objeto de visualización y libera su memoria. Como práctica recomendada, debe establecer cualquier objeto nulo
después de llamar quitarse
.
Invocamos esta función en el gameLoop
función.
function gameLoop () --SNIP-- movePlayer () movePlayerBullets () checkPlayerBulletsOutOfBounds () end
Si desea ver si esta función funciona correctamente, puede insertar temporalmente un imprimir ("Eliminación de viñetas")
declaración inmediatamente después de configurar el objeto de visualización para nulo
.
generarIsla
Para hacer que el juego sea más interesante, generamos una isla de vez en cuando y la movemos hacia abajo en la pantalla para dar la apariencia del avión que vuela sobre las islas. Agregue el siguiente fragmento de código para el generarIsla
función.
function generateIsland () local tempIsland = display.newImage ("island1.png", math.random (0, display.contentWidth - islandWidth), - islandHeight) table.insert (islands, tempIsland) islandGroup: insert (tempIsland) end
Hacemos uso de la nueva imagen
Método una vez más y posicionar la isla mediante el establecimiento de un valor negativo para el isla altura
. Para el X
posición, usamos el math.random
método para generar un número entre 0
y el monitor
es contenido ancho
menos el Isla Ancho
. La razón por la que restamos el ancho de la isla es para asegurarnos de que esté completamente en la pantalla. Si no restáramos el ancho de la isla, habría una posibilidad de que parte de la isla no estuviera en la pantalla..
Necesitamos iniciar un temporizador para generar una isla de vez en cuando. Agregue el siguiente fragmento de código al startTimers
función que creamos anteriormente. Como puedes ver, estamos generando una isla cadacinco segundos. En el siguiente paso, haremos que las islas se muevan..
function startTimers () firePlayerBulletTimer = timer.performWithDelay (2000, firePlayerBullet, -1) generateIslandTimer = timer.performWithDelay (5000, generateIsland, -1) end
moverIslas
La implementación de moverIslas
es casi idéntica a la movePlayerBullets
función. Verificamos si el islas
La tabla contiene cualquier isla y, si lo hace, la recorremos y movemos cada isla un poco..
función moveIslands () si (#islands> 0) entonces para i = 1, #islands do islands [i] .y = islands [i] .y + 3 end end end end
checkIslandsOutOfBounds
Al igual que verificamos si las balas del jugador se han movido fuera de la pantalla, verificamos si alguna de las islas se ha movido fuera de la pantalla. La implementación de checkIslandsOutOfBounds
Por lo tanto, debe ser familiar para usted. Verificamos si las islas. y
la posición es mayor que display.contentHeight
y si es así, sabemos que la isla se ha movido fuera de la pantalla y, por lo tanto, se puede eliminar.
función checkIslandsOutOfBounds () if (#islands> 0) luego para i = # islands, 1, -1 do if (islands [i] .y> display.contentHeight) luego islands [i]: removeSelf () islands [i] = nil table.remove (islands, i) end end end end end
generar vida gratuita
De vez en cuando, el jugador tiene la oportunidad de obtener una vida libre. Primero generamos una imagen de vida libre y si el jugador choca con la imagen, obtiene una vida extra. El jugador puede tener un máximo de seis vidas..
la función genereFreeLife () si (numberOfLives> = 6) y luego devuelve el final local freeLife = display.newImage ("newlife.png", math.random (0, display.contentWidth - 40), 0); table.insert (freeLifes, freeLife) planeGroup: insert (freeLife) end
Si el jugador ya tiene seis vidas, no hacemos nada al regresar temprano de la función. Si no, creamos una nueva imagen de vida y la agregamos a la pantalla. De manera similar a como posicionamos las islas antes, establecemos la imagen en un negativo y
Posición y generar un valor aleatorio para la imagen. X
posición. Luego lo insertamos en el freeLifes
Mesa para poder referenciarla más tarde..
Necesitamos llamar a esta función de vez en cuando. Agregue el siguiente fragmento de código al startTimers
función.
function startTimers () firePlayerBulletTimer = timer.performWithDelay (2000, firePlayerBullet, -1) generateIslandTimer = timer.performWithDelay (5000, generateIsland, -1) genera FreeLifeTimer = timer.performWithDelay (7000, generateFslive, 1)
mover vidas libres
La implementación de moveFreeLifes
debe parecer familiar. Estamos recorriendo el freeLifes
Mesa y mueve cada imagen en ella..
función moveFreeLifes () if (#freeLifes> 0) entonces para i = 1, # freeLifes do freeLifes [i] .y = freeLifes [i] .y +5 end end end
Todo lo que necesitamos hacer es llamar moveFreeLifes
en el gameLoop
función.
function gameLoop () --SNIP-- checkIslandsOutOfBounds () moveFreeLifes () end
checkFreeLifesOutOfBounds
El siguiente fragmento de código también debería parecerte familiar a estas alturas. Verificamos si alguna de las imágenes en el freeLifes
mesa se han movido fuera de la pantalla y eliminar los que tienen.
Función checkFreeLifesOutOfBounds () if (#freeLifes> 0) luego para i = # freeLifes, 1, -1 do if (freeLifes [i] .y> display.contentHeight) luego freeLifes [i]: removeSelf () freeLifes [i] = nil table.remove (freeLifes, i) end end end end end
Llamamos a esta función en el gameLoop
función.
function gameLoop () --SNIP-- checkIslandsOutOfBounds () moveFreeLifes () checkFreeLifesOutOfBounds () end
hasColido
Debemos poder saber cuándo los objetos del juego chocan entre sí, como el plano del jugador y las imágenes de vida libre, las balas y los planos, etc. Mientras Corona ofrece un motor de física muy robusto que puede manejar fácilmente las colisiones entre objetos de visualización Para nosotros, hacerlo agrega un poco de sobrecarga con los cálculos que el motor tiene que hacer en cada cuadro..
Para los fines de este juego, utilizaremos un sistema simple de detección de colisión de caja de delimitación. Lo que hace esta función es asegurarse de que los rectángulos o cuadros delimitadores alrededor de dos objetos no se superpongan. Si lo hacen, los objetos están chocando. Esta lógica se implementa en el hasColido
función.
La función hasCollided (obj1, obj2) if (obj1 == nil) devuelve el final falso if (obj2 == nil) luego devuelve el final falso local left = obj1.contentBounds.xMin <= obj2.contentBounds.xMin and obj1.contentBounds.xMax >= obj2.contentBounds.xMin derecho local = obj1.contentBounds.xMin> = obj2.contentBounds.xMin y obj1.contentBounds.xMin <= obj2.contentBounds.xMax local up = obj1.contentBounds.yMin <= obj2.contentBounds.yMin and obj1.contentBounds.yMax >= obj2.contentBounds.yMin local down = obj1.contentBounds.yMin> = obj2.contentBounds.yMin y obj1.contentBounds.yMin <= obj2.contentBounds.yMax return (left or right) and (up or down) end
Encontré este fragmento de código en el sitio web de CoronaLabs. Funciona realmente bien, porque los objetos del juego en nuestro juego son rectangulares. Si está trabajando con un objeto que no es rectangular, es mejor que aproveche el motor de física de Corona, ya que su detección de colisión está muy bien optimizada para esto..
checkPlayerCollidesWithFreeLife
Queremos comprobar si el avión del jugador ha colisionado con un objeto de vida libre. Si es así, le otorgamos al jugador una vida libre..
function checkPlayerCollidesWithFreeLife () if (#freeLifes> 0) luego para i = # freeLifes, 1, -1 do if (hasCollided (freeLifes [i], player)) luego freeLifes [i]: removeSelf () freeLifes [i] = nil table.remove (freeLifes, i) numberOfLives = numberOfLives + 1 hideLives () showLives () end end end end end end end
En el checkPlayerCollidesWithFreeLife
función, pasamos por el vidas libres
Tabla al revés por la misma razón que describí anteriormente. Llamamos al hasColido
Funciona y pasa en la imagen actual y en el plano del jugador. Si los dos objetos chocan, eliminamos la imagen de vida libre, incrementamos la número de vidas
variable, y llamar al ocultar vidas
y show Lives
función.
Invocamos esta función en el gameLoop
función.
function gameLoop () --SNIP-- moveFreeLifes () checkFreeLifesOutOfBounds () checkPlayerCollidesWithFreeLife () end
ocultar vidas
los ocultar vidas
la función pasa por el vidasImágenes
mesa y establece el es visible
propiedad de cada imagen de vida a falso
.
La función hideLives () para i = 1, 6 do livesImages [i] .isVisible = false end end
show Lives
los show Lives
la función pasa por el vidasImágenes
tabla y establece cada imagen de es visible
propiedad a cierto
.
función showLives () para i = 1, numberOfLives do livesImages [i] .isVisible = true; final fin
Esto cierra la tercera parte de esta serie. En la próxima y última entrega de esta serie, crearemos aviones enemigos y finalizaremos el juego del juego. Gracias por leer y nos vemos allí..