Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From \$16.50/m

# Create a Plane Fighting Game in Corona: Finishing Gameplay

Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called Create a Plane Fighting Game in Corona.
Create a Plane Fighting Game in Corona: More Gameplay

## Introduction

In the fourth and final part of this series, we continue where we left of in the previous tutorial. We'll create enemy planes the player needs to avoid or shoot, and we'll also create a game over screen.

## 1.`generateEnemys`

The `generateEnemys` function generates a number between three and seven, and calls the `generateEnemyPlane` function every two seconds for however many times `numberOfEnemysToGenerate` is equal to. Enter the following code snippet to gamelevel.lua.

We also need to invoke this function in the `enterScene` method as shown below.

Let's see what the implementation of `generateEnemyPlane` looks like.

## 2.`generateEnemyPlane`

The `generateEnemyPlane` function generates one enemy plane. There are three types of enemy planes in this game.

• Regular , moves down the screen in a straight line
• Waver, moves in a wave pattern on the x axis
• Chaser, chases the player's plane

We first check to make sure the game isn't over yet. We then generate a `randomGridSpace`, a number between 1 and 11, and a random `randomEnemyNumber`, a number between 1 and 3. The `randomGridSpace` is used to position the plane in one of eleven slots at the top of the screen on the x axis. If you think of the game area being divided into eleven sections, then we only want to place new planes in a slot that hasn't been taken yet by another plane. The `planeGrid` table contains eleven `0`'s and when we place a new plane in one of the slots, we set the corresponding position in the table to `1` to indicate that slot has been taken by a plane.

We check if the index of the `randomGridSpace` in the table isn't equal to `0`. If it isn't, we know that slot is currently taken and we shouldn't continue, so we call `generateEnemyPlane` and return from the function.

Next, we check what `randomEnemyNumber` is equal to and set `tempEnemy` to one of the three enemy images, we also give it a property of either `regular`, `waver`, or `chaser`. Because Lua is a dynamic language, we can add new properties to an object at runtime. We then set whatever index is equal to `randomGridSpace` to `1` in the` planeGrid` table.

We insert `tempEnemy` into the `enemyPlanes` table for later reference and increment `numberOfEnemysGenerated`. If `numberOfEnemysGenerated` is equal to  `numberOfEnemysToGenerate`, we reset `numberOfEnemysGenerated` to `0`, invoke `resetPlaneGrid`, and set a timer that will call `generateEnemys` again after two seconds. This process repeats for as long as the game isn't over.

## 3.`moveEnemyPlanes`

As you may have guessed, the `moveEnemyPlanes` function is responsible for moving the enemy planes. Depending on the plane's `type`, the appropriate function is called.

This function needs to be invoked in the `gameLoop` function.

## 4.`moveRegularPlane`

The `moveRegularPlane` simply moves the plane down the screen across the y axis.

## 5.`moveWaverPlane`

The `moveWaverPlane` function moves the plane down the screen across the y axis and, in a wave pattern, across the x axis. This is achieved by using the `cos` function of Lua's math library.

If this concept is foreign to you, Michael James Williams wrote a great introduction to Sinusoidal Motion. The same concepts apply, the only difference is that we are using cosine. You should think sine when dealing with the y axis and cosine when dealing with the x axis.

In the above snippet, we use the `numberOfTicks` variable. We need to increment this  each time the `gameLoop` function is called. Add the following as the very first line in the `gameLoop` function.

## 6.`moveChaserPlane`

The `moveChaserPlane` function has the plane chasing the player. It moves down the y axis at a constant speed and it moves towards the player's position on the x axis. Take a look at the implementation of `moveChaserPlane` for clarification.

If you test the game now, you should see the planes moving down the screen.

## 7.`fireEnemyBullets`

Every so often, we want the enemy planes to fire a bullet. We don't want all of them firing at the same time, however, so we choose only a couple of planes to fire.

We first check to make sure the `enemyPlanes` table has more than two planes in it. If it does, we get the `numberOfEnemyPlanes` to fire by taking the length of the `enemyPlanes` table, divide it by two, and round it down. We also make a copy of the `enemyPlanes` table, so we can manipulate it separately.

The `fireBullet` function chooses a plane from the `tempEnemyPlanes` table and makes the plane fire a bullet. We generate a random number based on the length of the `tempEnemyPlanes` table, create a bullet image, and  position it  by using whichever plane is at the `randIndex` in the `tempEnemyPlanes` table. We then remove that plane from the temporary table to ensure it won't be chosen again next time `fireBullet` is called.

We repeat this process however many times `numerOfEnemyPlanesToFire` is equal to and call the `fireBullet` function.

We need to start the timer that calls this function every so often. To accomplish this, add the following to the `startTimers` function.

## 8.`moveEnemyBullets`

We also need to move the enemy bullets that are on-screen. This is pretty simple using the following code snippet.

Invoke this function in the `gameLoop` function.

## 9.`checkEnemyBulletsOutOfBounds`

In addition to moving the enemy bullets, we need to check when the enemy bullets have gone off-screen and remove them when they do. The implementation of `checkEnemyBulletsOutOfBounds` should feel familiar by now.

Invoke this function in the `gameLoop` function.

## 10.`checkEnemyPlanesOutOfBounds`

We should also check if the enemy planes have moved off-screen.

Invoke this function in the `gameLoop` function

## 11.`checkPlayerBulletsCollideWithEnemyPlanes`

The `checkPlayerBulletCollidesWithEnemyPlanes` function uses the `hasCollided` function to check whether any of the player's bullets has collided with any of the enemy planes.

This function uses two nested `for` loops to check whether the objects have collided. For each of the `playerBullets`, we run through all the planes in the `enemyPlanes` table and call the `hasCollided` function. If there's a collision, we remove the bullet and plane, call the `generateExplosion` function, and load and play an explosion sound.

Invoke this function in the `gameLoop` function.

## 12.`generateExplosion`

The `generateExplosion` function uses Corona's SpriteObject class. Sprites allow for animated sequences of frames that reside on Image or Sprite Sheets. By grouping images into a single image, you can pull certain frames from that image and create an animation sequence.

The `newImageSheet` method takes as parameters the path to the image and a table of options for the Sprite Sheet. The options we set are the `width`, the `height`, and the `numFrames`, how many individual images make up this sheet. There are six separate explosion images as shown in the image below.

Next, we set up a table, `sequenceData`, which is needed by the `SpriteObject`. We set the `start` property to `1`, the `count` to `6`, and time to `400`.  The` start` property is the frame that the animation will start on, the `count` is how many frames the animation includes, and the `time` property is how long the animation takes to play through.

We then create the `SpriteObject` passing in the `explosionSheet` and `sequenceData`, set the x and y positions, and add a listener to the sprite. The listener will be used to remove the sprite once it has finished its animation.

## 13.`explosionListener`

The `explosionListener` function is used to remove the sprite. If the `event`'s `phase` property is equal to `ended`, then we know the sprite has finished its animation and we can remove it.

## 14.`checkEnemyBulletsCollideWithPlayer`

The `checkEnemyBulletsCollideWithPlayer` checks to see if any of the enemies' bullets have collided with the player's plane.

We loop through the `enemyBullets` table and check if any of them have collided with the player. If true, we remove that particular bullet, and, if `playerIsInvincible` is `false`, we invoke `killPlayer`.

Invoke this function in the `gameLoop` function.

## 15.`killPlayer`

The `killPlayer` function is responsible for checking whether the game is over and spawning a new player if it isn't.

We first decrement `numberOfLives` by `1`, and, if it's equal to `0`, we call the `gameOver` function. It the player has lives left, we call `spawnNewPlayer`, followed by `hideLives`, `showLives`, and set `playerIsInvincible` to `true`.

## 16.`doGameOver`

The `doGameOver` function tells the storyboard to go to the gameover scene.

## 17.`spawnNewPlayer`

The `spawnNewPlayer` function is responsible for spawning a new player after it has died. The player's plane blinks for a few seconds to show that it's temporarily invincible.

To make the player's plane blink, we fade it in and out five times. In the `fadePlayer` function, we set the plane's `alpha` property to `0`, which makes it transparent. We then use the transition library to fade the `alpha` back to `1` over a period of 200 milliseconds. The `to` method of the `transition` object takes a table of options. In our example, the options table includes a time in milliseconds and the property we'd like to animate, `alpha`, and the desired value, `1`.

We increment `numberOfTimesThePlayerHasFaded` and check if it's equal to the number of times we wanted the player to fade. We then set `playerIsInvincible` to `false`. We use a timer to call the `fadePlayer` function however many times `numberOfTimerToFadePlayer` is equal to.

There is a way to do all this without using the timer and that is by using the `transition`'s `iterations` property in combination with its `onComplete` handler. Read through the documentation to learn more about this alternative approach.

## 18.`checkEnemyPlaneCollidesWithPlayer`

There is one more collision check we should do and that is to see if an enemy plane collides with the player's plane.

We loop through the enemy planes and see if any one of them collides with the player's plane. If true, we remove that enemy plane and call `killPlayer`. If you think it makes the game more interesting, you could also generate an explosion here.

## 19.`exitScene`

When the game is over, we transition to the gameover scene. Remember from earlier in the tutorial, the `exitScene` function is where you remove any event listeners, stop timers, and stop audio that's playing.

We are basically undoing what we did in the `enterScene` function. We call the `dispose` method on the `audio` object to release the memory associated with the audio channel. Calling `stop` alone does not release the memory.

## 20.`cancelTimers`

As its name indicates, the `cancelTimers` function does the opposite of  `startTimers`, it cancels all the timers.

## 21. Game Over Scene

It's time to create the gameover scene. Start by adding a new Lua file to your project named gameover.lua, and add  the following code to it.

## 22.`createScene`

Add the following to gameover.lua above `return scene`. From here on out, all code should be placed above the `return scene` statement.

As we did in the previous two scenes, we give the gameover scene a blue background. We then create a `TextObject` instance by calling `newText` on `display`. The `newText` method takes a few options, the text for the object, its position, and the font to use. We give it a yellow color by invoking `setFillColor`, passing in RGB values as percentages. Finally, we create a button and hide it for the time being.

## 23.`enterScene`

When the storyboard has fully transitioned to the gameover scene, the `enterScene` method is called.

In `enterScene`, we remove the previous scene from the storyboard. We use the convenience method `scaleTo` from the Transition Library to scale the `gameOverText` by a factor of `4`. We add an `onComplete` listener to the transition that calls the `showButton` function once the transition has completed. Lastly, we add a tap event listener to the game button that invokes the `startNewGame` function.

## 24.`showButton`

The `showButton` function hides the `gameOverText` and shows the `newGameButton`.

## 25.`startNewGame`

The `startNewGame` function tells the storyboard to transition to the gamelevel scene.

## 26.`exitScene`

We need to do some cleanup when we leave the gameover scene. We remove the tap event listener we added earlier to the `newGameButton`.