Corona – Tower Defense Game Experiments 6.2

plants vs Zombies works on a strict grid with enemies advancing in rows, and defenses firing only on their row. Other tower defense games allow defenses to fire at any enemy within range. The last post tested an example that had defenses firing only within their row. In this example I will create defenses that fire at any enemy within range.

Get Distance to enemy

To get the distance to an enemy in pixels we can take the Pythagorean formula: a2 + b2 = c2. In Lua terms this might look like:

c = math.sqrt((a*a)+(b*b))

To make this more useful and easier to work with we can wrap it in a function that returns the distance between two points. The example below takes two sets of x and y values and returns the distance between these points.

local function get_distance( x1, y1, x2, y2 )
	local dx = x1 - x2
	local dy = y1 - y2
	return math.sqrt( (dx*dx) + (dy*dy) ) -- Return the distance
end

If you’re feeling Object Oriented, you could make a a point object and pass that to the function. Lua is not an Object Oriented language so we would need to use a table and factory function, but this has a very similar arrangement.

local function Point( x, y )
	return {x=x, y=y}
end

local function get_distance( point_1, point_2 )
	local dx = point_1.x - point_2.x
	local dy = point_1.y - point_2.y
	return math.sqrt( (dx*dx) + (dy*dy) ) -- Return the distance
end

With this method, using either of the two functions above, a defense can make the decision to fire on an enemy when that enemy is within range.


Deciding when to fire

The defense_defend( defense ) function is called from the timer assigned to a defense. Here we need to examine each enemy and measure the distance between the enemy and the defense. If the range is less a specified range we have the defense fire at that enemy.

I set the range of the defense as a “constant” at the top of script for easy use.

local DEFENSE_RANGE = 250

Next I need to modify defense_defend(defense) to work with the get_distance(x1,y1,x2,y2) function above. I used the first function in this example. Here we loop through the alien_array and look at the distance to each alien. If there is an alien within range we fir on it and break the loop.

-- This new function will look at the board and find eligible targets
local function defense_defend( defense )
	for i = 1, #alien_array, 1 do 		-- Loop through alien_array
		local alien = alien_array[i]	-- get the alien

		if get_distance( defense.x, defense.y, alien.x, alien.y ) < DEFENSE_RANGE then -- Check the distance
			make_bullet( defense.x, defense.y, alien.x, alien.y )
			break
		end
	end
end

Since get_distance(x1,y1,x2,y2) returns the distance as a number we can place this function call inside the if expression:

if get_distance( defense.x, defense.y, alien.x, alien.y ) < DEFENSE_RANGE then ...

I will also have to modify the make_bullet() function to allow it fire on a target anywhere on the screen. You’ll notice this function has been modified from make_bullet(x,y) to make_bullet(x1,y1,x2,y2).

Sending bullet toward the target

Using this method bullets will be fired across columns. This means I will have to animate both the x and the y of the bullet. In the previous versions I had only animated the y value of the bullet. In these versions bullets were animated to a y of 0, targeting the top edge of the screen.

To make this happen I need to modify the make_bullet( x, y ) function. Before the function only had to send a bullet to the top of the screen, in which case all that was needed was a starting position. Now it needs to know the position of the target also. So here we’ll modify make_bullet(x,y) to make_bullet( start_x, start_y, target_x, target_y ).

Since the distance to the target will always be different we’ll need to get the distance again and multiply by the constant BULLET_SPEED, thus making sure the bullets move at a consistent speed no matter what the distance.

Here’s a new version of the make_bullet() function

local function make_bullet( start_x, start_y, target_x, target_y )
	local bullet = display.newCircle( 0, 0, 5 )
	bullet:setFillColor( 0, 0, 0 )
	bullet.x = start_x
	bullet.y = start_y
	table.insert( bullet_array, bullet )

	-- The bullet speed and transition need to be retooled
	-- We will end up calling get_distance twice, we could optimize by passing the distance from defense_defend
	local d = get_distance( start_x, start_y, target_x, target_y )  -- Get the distance to the target
	local bt = d * BULLET_SPEED 

	bullet.transition = transition.to( bullet, {y=target_y, x=target_x, time=bt, onComplete=remove_bullet} )
end

Following the flow of code here, the defense_defend() function calls on get_distance(). If an enemy is within the distance we move on to make_bullet(). Where make_bullet() calls on get_distance() again. There’s room for a small performance optimization here. We could pass the distance to make_bullet() and not have to do the math again. I’ll things as they are for now, and may be address this in a future update.

Here’s a full listing of the code for this example:
Continue reading Corona – Tower Defense Game Experiments 6.2

Corona – Tower Defense Game Experiments 6.1

Defensive Firing Habits

This time the goal will be to control the firing habits of defense elements. There are several factors that can be used to control the firing habits of defenses.

Distance to enemies

The distance to an enemy can be set for defense. This gives the option choosing defenses with greater or lesser range.

Column position

In Plants vs Zombies defenses only fire at enemies in the same column and distance is not a factor. Though, this could be combined with distance for more variation.

Firing angle

In the original experiments the defenses only fire straight up the screen. There’s nothing to stop us from having defenses fire at an enemy in any column, except a few lines of code.

Firing at enemies in same column

In this experiment we’ll make the defenses fire only when there is an enemy in their column. To make this happen defenses and enemies will have to know their column number.

make_alien()

When enemies are created I choose a random column and position the enemy in that column. At this time we need to add a property variable to the enemy and set it to the column number. The place for this to happen is make_alien().

NOTE: I realized when I created the earlier version I used the name row, when I setting the column! So I changed this variable name to col.

local function make_alien()
	local alien = display.newRect( 0, 0, 32, 32 )
	alien:setFillColor( 0, 200, 0 )

	local col = math.random( 1, TILE_COLS ) -- Oops! I had previously used row instead of col here!
	alien.col = col 			-- Assign this alien his col position
	alien.x = col * ( TILE_SIZE  + TILE_MARGIN )
	alien.y = 0
	alien.life = 5 

	local target_y = ( TILE_SIZE + TILE_MARGIN ) * TILE_ROWS
	local t = ( TILE_ROWS + 1 ) * 2000
	alien.transition = transition.to( alien, {y=target_y, time=t, onComplete=remove_alien} )
	alien_group:insert( alien )
	table.insert( alien_array, alien )
end

make_grid()

When creating defense elements we tap on a tile. The tile positions the new defense at the tile’s location. Since defense will no need to know their column number, the tile will also need to know it’s column number so it can pass it along to the defense that is created. Tiles are created in the make_grid() function. Here I added one line of code assigning a new property variable, col, to each tile.

local function make_grid()
	for row = 1, TILE_ROWS, 1 do
		 for col = 1, TILE_COLS, 1 do
		 	local tile = display.newRect( 0, 0, TILE_SIZE, TILE_SIZE )
		 	tile.x = ( TILE_SIZE + TILE_MARGIN ) * col
		 	tile.y = ( TILE_SIZE + TILE_MARGIN ) * row 

		 	tile.col = col -- Tiles need to know col

		 	tile.has_defense = false  

		 	tile:addEventListener( "touch", touch_tile )
		 	tile_group:insert( tile )
		 end
	end
end

touch_tile()

Touching a tile creates a defense. Touch events on tiles are handled in the touch_tile() handler. Here we need to get the column number from the tile and assign it to the new defense that is created. Earlier I had just made a defense with getting a reference to the defense. Note that the make_defense() function does return the new defense created! I had ignored the return value previously. We’ll use it now. Here we get a reference to the new defense and assign it a new property variable.

local function touch_tile( event )
	local phase = event.phase
	if phase == "began" then
		local tile = event.target
		local tile_x = tile.x
		local tile_y = tile.y

		local defense = make_defense( tile_x, tile_y ) -- Get a reference to the new defense defense.col = tile.col -- assign the col to the new defense
	end
end

make_defense()

Next we need defenses to think before they shoot. Each defense will need to look at all of the enemies on the screen and check their col agains the col of the defense. If cols match the defense fires, others not. To do this I added an intermediate function call from the timer, rather than call make_bullet() directly from the timer.

The new function, defense_defend( defense ), takes the defense as a parameter.

The defense timer is created when the defense is created, in make_defense(). Here’s an updated version of make_defense():

local function make_defense( x, y )
	local defense = display.newRect( 0, 0, 32, 32 )
	defense:setFillColor( 200, 0, 0 )

	defense_group:insert( defense ) 

	defense.x = x
	defense.y = y

	table.insert( defense_array, defense ) 

	-- Change the timer handler to call defense_defend( defense )
	defense.timer = timer.performWithDelay( 1000, function() defense_defend( defense ) end, -1 )

	return defense
end

defene_defend()

The defense_defend( defense ) function needs to examine all of the enemies and check their col. Here I will use a loop to look at each of the enemies in the alien_array. Since defenses can only fire once, if we find a target we break the loop, and stop checking for new enemies.

-- This new function will look at the board and find eligible targets
local function defense_defend( defense )
	for i = 1, #alien_array, 1 do 		-- Loop through alien_array
		local alien = alien_array[i]	-- get the alien
		if alien.col == defense.col then -- check column
			make_bullet( defense.x, defense.y )
			break
		end
	end
end

Time to test! If everything is working correctly defense should now only fire when there is an enemy in their column.

Here’s a listing the entire code for this version:

Continue reading Corona – Tower Defense Game Experiments 6.1

Corona – Tower Defense Game Experiments 5

Destroying Aliens with bullets

In the last post I created bullets that fire from a defense at advancing enemies. I still need to check if an enemy is hit, and if so reduce it’s life, and remove it if it has reached 0 life.

I see many example that would use physics for the collision detection for this. I feel that physics may be over kill for what I am doing here. it’s also my guess that using physics would add a lot of processing overhead. Physics also brings up other problems that need to be solved. All in all I physics, in this case will create more problems than it solves. So, I’m going to opt to use a hit test and manage bullets and alien enemies in arrays.

A few notes on code styles. The code is now getting longer and so I decided to make a few style changes to help me keep organized. Constants, these are variables that will not change value. These will be UPPER_CASE. Lua doesn’t have actual constants, I’m using upper case as a reminder.

Hit Test – Bullets vs Aliens

For each bullet fired, I will need to check if that bullet hits an enemy. To determine a hit take the x and y location of the bullet and check if it is inside the bounds of the enemy. The bounds of an object is represented by four values that define the edges of the rectangle surrounding the object. Use display.contentBounds to get the bounds object. This object will have properties of:

  • xMin (defines the left edge)
  • xMax (defines the right edge)
  • yMin (defines the top edge)
  • yMax (defines the bottom edge)

To determine if a point, an x and y pair, is within the bounds of an object use an if statement to compare the bounds properties and the x and y of the point. Check if the x value is greater than xMin and less than xMax, while the y value is greater than yMin and less than yMax. Something like this:

if x > bounds.xMin and x < bounds.xMax and y > bounds.yMin and y < bounds.yMax then
... HIT! ...
end

Checking for a single hit is simple and straight forward. With multiple bullets and enemies on the screen at the same time the problem is a more complicated. For each bullet we need to check for a hit against each enemy. To organize this, all bullets need to be in an array and all enemies in another array. In the future I may want enemies to attack defenses so, I made an array to hold defenses also.

local defense_array = {}
local alien_array = {}
local bullet_array = {}

With the bullets in an array and the enemies in another array we can look at each bullet and perform a hit test against each enemy with that bullet.

Making Bullets

I used the same strategy for bullets that was used for other display elements tiles, aliens and defenses. I need a function to make bullets and another to remove them.

BULLET_SPEED

I used a transition to move the bullets up the screen. The time it takes a bullet to move up the screen will vary by the distance the bullet has to travel. To get the bullets to move at a consistent rate I created the variable BULLET_SPEED. This is a “constant”, that is it’s value will NOT change while the program runs. Corona and Lua do not support actual constants, but this is the intent for this variable, so I will use a style to mark it as such.

I set the speed in pixels per millisecond (1/1000 of a second). I decided on a speed of 400 pixels per second. In milliseconds this becomes 1000 / 400.

local BULLET_SPEED = 1000 / 400

To create transition that moves at this constant rate multiply the distance by BULLET_SPEED and set this value as the time of the transition.

Bullets will be black circles, for now.

Here are two functions to make and remove bullets.

local function remove_bullet( bullet )
	local index = table.indexOf( bullet_array, bullet )
	transition.cancel( bullet.transition )
	table.remove( bullet_array, index )
	display.remove( bullet )
end

local function make_bullet( x, y )
	local bullet = display.newCircle( 0, 0, 5 )
	bullet:setFillColor( 0, 0, 0 )
	bullet.x = x
	bullet.y = y
	table.insert( bullet_array, bullet )

	local bt = y * BULLET_SPEED
	bullet.transition = transition.to( bullet, {y=0, time=bt, onComplete=remove_bullet} )
end

To detect a hit I need to look at the position of each bullet and alien and apply a hit test each frame. I added an enterFrame event and handler. I also separated the hit test into it’s own function since it might be useful for other purposes in the future. Note the hit test returns true on a hit or false. This way you can place a hit test inside of an if statement, as in the code below:

local function hit_test( x, y, bounds )
	if x > bounds.xMin and x < bounds.xMax and y > bounds.yMin and y < bounds.yMax then
		return true
	else
		return false
	end
end 

local function on_enterframe( event )
	for b = 1, #bullet_array, 1 do
		local bullet = bullet_array[b]

		if b > #bullet_array then
			return
		end

		for a = 1, #alien_array, 1 do
			local alien = alien_array[a]

			if hit_test( bullet.x, bullet.y, alien.contentBounds ) then
				if alien.life > 0 then
					alien.life = alien.life - 1
				else
					remove_alien( alien )
				end
				remove_bullet( bullet )
				break
			end
		end
	end
end

Runtime:addEventListener( "enterFrame", on_enterframe )

Here’s a full code listing so far.
Continue reading Corona – Tower Defense Game Experiments 5

Corona – Tower Defense Game Experiments 4

Bullets

In the last couple posts I modeled some simple ideas for creating a Tower Defense game like Plants vs Zombies. So far I have a tiled background, enemies that advance down the screen, and the ability to add a defense at any particular tile.

At this point the defense and the enemies still do not interact. The next step is to give the defense elements the ability to fire bullets at the advancing enemies.

Bullet Factory

Throughout the process I have been using a system based on “factory functions” to create new objects. I like this method it keeps me organized. I’ll use it again to create bullets. Though Lua is not an OOP language factory functions have some the feeling of using new to create an instance.

The bullets will be simple circles. I will use a transition.to() to move the bullets up the screen.

The make_bullet() function takes the starting x and y position of the bullet.

local function remove_bullet( bullet )
	display.remove( bullet )
end

local function make_bullet( x, y )
	local bullet = display.newCircle( 0, 0, 5 )
	bullet:setFillColor( 0, 0, 0 )
	bullet.x = x
	bullet.y = y

	bullet.transition = transition.to( bullet, {y=0, time=1000, onComplete=remove_bullet} )
end

Calling functions from timer.perfromWithDelay()

Now it’s time to send the bullets up the screen. To make this happen I’ll use a timer. Each defense element will need a timer. I’m adding a reference to each timer as it is created, to the defense element the timer is created with. This way if a defense element is destroyed in the future that element will be able to cancel it’s timer.

defense.timer = timer.performWithDelay( 1000, function() make_bullet( defense.x, defense.y ) end, -1 )

The second parameter is a function, that is called with each timer event. We need to call make_bullet(x,y), this function requires the x and y location of the bullet. We can’t write this as:

-- WRONG!
defense.timer = timer.performWithDelay( 1000, make_bullet( defense.x, defense.y ), -1 )

Here we would be invoking make_bullet( defense.x, defense.y ) at the time we created he timer. The effect would be one bullet fired, rather than firing a bullet with each timer event. The timer in this case would act on what was RETURNED from make_bullet(), which would be nil.

In the correct format above I wrapped the call to make_bullet( defense.x, defense.y ) in a function. This is interesting because defense is a local variable and lost when make_defense() ends. The handler function defined inside the timer function encloses the variable defense (defense.x and defense.y) effectively preserving the values they had at the time that this function was defined.

Since this project has gone through a few changes, I’ll post the full source code I have been using up to this point for reference.

Continue reading Corona – Tower Defense Game Experiments 4

Corona – Tower Defense Game Experiments 3


Defense

The last two posts made a simple game with a tiled playing field and enemies that cross the screen. Now I’d like to add some defense. The goal of the defense elements is to keep enemies from crossing the screen and reaching the other side.

The first step is to create a factory function to generate defensive elements for the game. As a first step we’ll start with a single type of defense and use a red rectangle for art. Here’s a simple function that generates a red square and places at x and y coordinates passed to the function.

local function make_defense( x, y )
	local defense = display.newRect( 0, 0, 32, 32 )
	defense:setFillColor( 200, 0, 0 )
	game_group:insert( defense )

	defense.x = x
	defense.y = y

	return defense -- Return the new defense
end

This function returns the newly created defense. This allows any other function that calls make_defense() to work with the newly created defense, saving a reference, or adding or editing properties of the defense.

Touching the grid

Our defenses should end up on the tile grid. We can use the x and y of the grid square to position the new defense. The grid square can also keep track of it’s contents which we can use to make sure we don’t add more than one defense per square.

Add an event listener to each grid square inside the make_grid() function:

tile:addEventListener( "touch", touch_tile )

Now define touch_tile(). This will have to go above make_grid(), and the make_defense() function will have to be placed above touch_tile().

local function touch_tile( event )
	local phase = event.phase
	if phase == "began" then
		local tile = event.target
		local tile_x = tile.x
		local tile_y = tile.y

		make_defense( tile_x, tile_y )
	end
end

Here we check the event phase. If the phase is “began” then we’ll add a defense at this tile. First get a reference to the tile then get that tile’s x and y. Last call make_defense and pass the tile coordinates.

Testing, at this stage tapping a tile should display a red square centered on that tile.

There are a few problems. Defense elements will appear above some enemies and below others. Each new display item is added to the top of the display list, and appears in front of already existing display items in a group. Items in a group stack at the position of their group inside the parent element.

Using groups to layer elements

As a first idea let’s add a group for each type of element: tile, defense, and alien. We’ll place all of these groups into game_group. Then add each element, tile, alien and defense, as it is created to it’s name group. This will make all like elements stack together.

local game_group = display.newGroup()
local defense_group = display.newGroup() 	-- make a group to hold each class
local alien_group = display.newGroup()		--
local tile_group = display.newGroup()

game_group:insert( tile_group )		-- Add each group to the main group
game_group:insert( defense_group )
game_group:insert( alien_group )

You’ll need to edit the make_grid(), make_alien(), and make_defense() functions so these add the elements they create to the proper group.

Testing again, this time all of the defense elements will always be above the background tiles and below the enemies.

Creating a single defense in each grid square

There is a problem that a new defense is created with each touch on a tile. This won’t be visible, since the defense rectangles are stacked on above another, but it will be happening.

To fix this assign each tile a variable to keep track of whether it has a defense or not.

tile.has_defense = false

Next add an if statement to the touch_tile() handler.

if tile.has_defense == false then	-- Check that tile has no defense
	tile.has_defense = true		-- mark this tile as now having a defense
	local tile_x = tile.x
	local tile_y = tile.y

	make_defense( tile_x, tile_y )
end

Now, if a tile is touched, we first check it for a defense. If no defense is present, tile.has_defense = false, then we add a defense and set tile.has_defense to true. On the next touch no defense would be added.

Corona – Tower Defense Game experiments 2

Quote from a fan

In the last post I set an outline for a tower defense game based on Plants vs Zombies. My child says: “Plants vs Zombies is awesome, and I defeated Zombies until I got the hypnoshroom!”. So it must be pretty fun.

Theme

Plants vs Zombies has a great theme, and many interesting features and characters. The game play is simple, but wrapped in great art and concept. This is the key to any successful game.

Destroy Enemies

The next step is create enemies that we can destroy. In plants vs zombies, enemies can be hit multiple times before they are destroyed. This is an interesting game idea. It allows us to create enemies that can take more or fewer hits than other enemies. It also allows us to create weapons that deal more or less damage to enemies. These types of options allow players more interesting game play. It’s all about choice. It’s also about balance, but we’re getting ahead of ourselves.

At this stage we need to assign each enemy a value to keep track of how much damage it has taken. We will also need to monitor this value and remove the enemy when it reaches 0. To keep things simple at this stage in this example touching a zombie will apply damage to a zombie.

Dynamic objects

In Corona all objects are Dynamic. In this context Dynamic is a programming term. Dynamic objects allow you to add properties to them. Essentially this means we can create a new variables that objects carry around. In the case of the enemies in our game we’ll add a property called life. This will be a number that sets the number of times the enemy can be tapped before it is removed from from the screen.

When each object is added to the screen we need to add the life property to it. Inside the make_alien() function, after alien is defined add:

alien.life = 5

Now each alien created will also have a variable attached to it named life, and each alien will keep track of it’s own value for life. In this way each alien can have different values for life.

Next add a touch event to the alien:

alien:addEventListener( "touch", touch_alien )

I’m using a touch event here because it will react to a touch down on the screen. A tap event would not be fired until after your finger leaves the screen. This will make our game more responsive.

The last step is to define our handler touch_alien(). Remember, in Lua you need to define this function before we call on it, so it will have to be defined above make_alien(), or we need to add a forward declaration above.

local function touch_alien( event ) -- This handles touches on aliens.
	local phase = event.phase
	if phase == "began" then 			-- Check the phase.
		local alien = event.target		-- Get the target
		alien.life = alien.life - 1		-- reduce alien life total by 1
		if alien.life <= 0 then 		-- if 0 or less
			transition.cancel( alien.transition ) -- cancel transition
			remove_alien( alien )		-- remove alien
		end
	end
end

This function first checks the event phase. If the phase is “began” then it gets a reference to the alien that initiated the event via event.target. I used the variable name alien here for consistency. Next subtract 1 from the alien’s life. Last check the life total. If it 0 or less, remove the transition and remove the alien.

Testing the game. Touching an alien 5 times should remove it from the screen.

 

Corona – Tower Defense Game experiments 1

Plants vs Zombies

My child developed a fascination with Plants vs Zombies on the iPhone. The game looks fairly addictive though, I haven’t actually gotten a chance to play yet. The art is great and the levels and mini games look like fun.

Tower Defense

The game is in the Tower Defense category. In a nutshell enemies attack by moving across the game field. You place “towers” to defend your territory. You can spend points to buy defenses of varying cost and capabilities. The concept an theme behind Plants vs Zombies is Zombies attacking your house. Which you defend by planting plants.

The game is played on a grid with zombies advancing along rows. You play defensive plants in grid squares. This makes for a simple layout.

This project covers many posts. Click the tag tower defense to list all of the posts in the series.

Getting started

To be honest I’m starting this with only vague ideas as to how to get to the end result. So a few test demos are in order. First things first lets make a grid and some enemies that will move across the grid.

For now we’ll keep things simple by using rectangles instead of images for the grid and enemies. I imagine I’ll create some sprites later on. By sticking with simple shapes it will be easier to program and share code also.

Creating a grid

To create a grid we’ll define a few variables. We need to know the number of rows and columns. Rows run horizontally and columns run vertical. We’ll put a rectangle in each grid square. These rectangles can help use located taps and position defenses.

To build the grid we need to know size of each grid square and the margin between squares. To get started I defined some variables to define the grid. I started with squares, so tile_size will cover both height and width of the grid squares.

local tile_rows = 9
local tile_cols = 5
local tile_size = 48
local tile_margin = 1

Plants vs Zombies uses a 6 by 10 grid. Here I have 9 rows by 5 columns. Each square is 48px by 48px with a 1 px margin. Keeping all of these values in variables at the top of the script makes it easy to edit the values and change the size of the grid. We can also uses these values to determine the positioning and animation of enemies.

Container Group

It’s probably a good idea to keep all of the game elements inside of a group. Best to do this now, if we don’t we will most likely find that we need to do it in the future.

local game_group = display.newGroup()

From here all game elements will be added to this group. If everything is in the group we can easily move all of the elements, or scale them. This can be good for things like transitioning between levels, and showing areas outside the playing field (Plants vs Zombies uses this).

Create grid squares

Next write a function to create the grid squares.

local function make_grid()
	for row = 1, tile_rows, 1 do
		 for col = 1, tile_cols, 1 do
		 	local tile = display.newRect( 0, 0, tile_size, tile_size )
		 	tile.x = ( tile_size + tile_margin ) * col
		 	tile.y = ( tile_size + tile_margin ) * row
		 	game_group:insert( tile )
		 end
	end
end

Here I have a function containing two nest loops. The outer loop counts to the number of tile rows with the variable rows. While the inner loop counts to the number of tile columns with the variable cols.

Each tile is a rectangle of tile_size equal to the height and width. Each tile is spaced tile size plus margin. Multiply x by col and y by row to place them all in a grid. Last, each tile is inserted into game_group. For the time being the tiles are white. These could be any color, or replaced with an image in the future. You could also give them a transparent color and place an image under the grid.

make_grid()

Add a call to make_grid() to test this out. Try changing the variables at the top to change the size and spacing of the grid. Position the whole group of grid squares by setting the x and y of the game_group.

Create enemies

In this example enemies will be green rectangles. Enemies will start in one of the 5 columns at the top of the screen and advance down the screen. I’m thinking about making the theme of the game aliens invading from space. So the game play will be vertical. Aliens will be the enemies and humans will be defending.

I started with a function that will return an enemy. The function will create the display object and initialize it by setting any relevant properties. This display object will be a local variable, as such it will only exist inside of this function. Keeping variables local will help reduce memory leaks. As a rule I use the same name for the same element everywhere it might show up as a local variable. You can see this below. The variable alien appears in both functions, but is local in both.

Since the concept for my game is aliens invading I’ll call my functions make_alien() and remove_alien(), make_alien() will make new enemies, while remove_enemy() will remove enemies when needed.

local function remove_alien( alien )
	display.remove( alien )
end 

local function make_alien()
	local alien = display.newRect( 0, 0, 32, 32 )
	alien:setFillColor( 0, 200, 0 )
	local row = math.random( 1, tile_cols )
	alien.x = row * ( tile_size  + tile_margin )
	alien.y = 0
	local target_y = ( tile_size + tile_margin ) * tile_rows
	local t = ( tile_rows + 1 ) * 2000
	alien.transition = transition.to( alien, {y=target_y, time=t, onComplete=remove_alien} )
	game_group:insert( alien )
end

Enemies will move via transition.to(). The onComplete property of the transition table will be used to remove the enemy when they have crossed the board. The onComplete call will provide a reference to the object that finished the transition. So in this case alien in remove_alien( alien ) is the same object that was used in transition.to( alien, {…}).

I assigned each alien a transition property and assigned this property a value pointing to the transition that is handling the movement of this object. If an enemy is removed before the transition is complete we will need to cancel the that transition. I’m expecting enemies to be removed as part of game play.

Create enemies with a timer

The last step in this example is to use a timer to call make_alien() periodically. Aliens will remove themselves when their transition is complete.

local alien_timer = timer.performWithDelay( 2300, make_alien, -1)

The timer defined above, calls on make_alien() every 2300 milliseconds, or 2.3 seconds, and loops for ever.

Test your work. Green squares, Aliens, should appear at the top of the screen and move down the screen. Reaching the bottom of the screen they should disappear.

 

Corona – Factory Functions

Functions

Thinking of functions as reusable blocks of code, factory functions make easy work out of creating objects common to any Corona project.

The key component to making a factory function is the key word return. Functions can return values. When a function returns a value the functions ends immediately and any code following return is not executed. The value returned can be any value. In Lua, unlike many other languages, functions can return multiple values.

Functions can also receive values. The values received, often called arguments or parameters make functions really flexible.

Corona has many built in Factory functions, all under the display class.  These functions all return a display object of varying types, text, rectangle, circle, image etc. If you are just making a simple object thee are good enough. Many times though, you will want to return a more specific type of object.

For example just creating a circle can be handled with the factory function: display.newCricle(left, top, radius), while useful is not usually the end of the process. Most often you will want to create a circle at a particular size, color and location. In these cases you’ll need more than display.newCircle(). For example:

local radius = math.random(10, 30)
local circle = display.newCircle(0,0,radius)
circle.x = math.random(30, 290)
circle.y = math.random(30,450)
local r = math.random(0, 255)
local g = math.random(0, 255)
local b = math.random(0, 255)
circle:setFillColor( r, g, b )

Wow that’s a lot of code to make a circle of random size and color. We don’t want to have to repeat, or have it clog up the rest of our project logic.

Imagine expanding this into a loop that creates 30 circles.

 

for i = 1, 30, 1 do
local radius = math.random(10, 30)
local circle = display.newCircle(0,0,radius)
circle.x = math.random(30, 290)
circle.y = math.random(30,450)
local r = math.random(0, 255)
local g = math.random(0, 255)
local b = math.random(0, 255)
circle:setFillColor( r, g, b )

end

This works just fine, and there’s nothing wrong with it. But it could be improved in a few ways.

Leave well enough alone?

Of course not! Not when it comes to programming. This type of thinking gets you in more trouble than you can imagine. As your program grows being able to, identify and modify previously written code becomes essential. Using a factory function allows you to separate defining an object from creating the object.

Think of defining an object as determining all an object’s starting characteristics. While creating the object, creates a new instance of the object.

Making a circle Factory

Here’s a function that creates circles with random color, size and position.

local function make_circle()
	local radius = math.random( 10, 30 )
	local circle = display.newCircle( 0, 0, radius )
	circle.x = math.random( 30, 290 )
	circle.y = math.random( 30, 450 )
	local r = math.random( 0, 255 )
	local g = math.random( 0, 255 )
	local b = math.random( 0, 255 )
	circle:setFillColor( r, g, b )

	return circle
end

The code above is essentially the original code snippet wrapped in a function. The key feature, and what makes this a factory, is the last line: return circle.

Internally the function creates a new shape object and stores it in the variable circle. This variable local to the function and not accessible outside of the function. Using the return keyword we can pass circle along to some other part of our program.

Making circles with make_circle()

Imagine we want to make 30 circles. With the new factory we now only need to add:

for i = 1, 30, 10 do 
	local circle = make_circle()
end

 Why is this better than the first example:

Separating the code defining the circle objects from the code that actual creates them provides a couple advantages: It’s easier to understand and More flexible.

Easier to understand

When breaking code up like this if you need to change the look of the circle you can edit the make_circle function. Here you are altering only the default definition of the object which isn’t embedded along with other code.

More Flexible

Since we have a function that creates circles we can create circle from other areas of our program without having to duplicate code. Anytime you need a circle just call make_circle().

Color Object

Might as well improve on our system of setting the colors of objects. Rather than defining each of the color components, r, g and b, each time we need a color, we’ll wrap all of these up in a single object/table with properties r, g and b. Here’s a sample function:

local function Color( red, green, blue )
	return {r=red, g=green, b=blue}
end

The function above takes three values, combines them into a table. This table has properties of r, g and b. The function returns the table.

You might use it in this way. Imagine you wanted to create a color object representing the color red.

local red_color = Color( 255, 0, 0 )

You could then use the red_color in this way:

circle:setFillColor( red_color.r, red_color.g, red_color.b )

The beauty of this system is leads to better and more organized code in the future. With the color stored in an organized form we can start writing functions that transform our Color object by adjusting the hue, saturation and lightness. We can also share a Color object with other objects easily.

Random Color

Our system needs a random color. In this case we might as well make another function that will work with out Color object to return a random color.

local function random_color()
	local r = math.random( 0, 255 )
	local g = math.random( 0, 255 )
	local b = math.random( 0, 255 )

	return Color( r, g, b )	
end

Here define some random values for the red, green and blue color components then create a new color object from those values and return it.

Use this to further simplify the circle factory function:

local function make_circle()
	local radius = math.random( 10, 30 )
	local circle = display.newCircle( 0, 0, radius )
	circle.x = math.random( 30, 290 )
	circle.y = math.random( 30, 450 )

	local color = random_color()
	circle:setFillColor( color.r, color.g, color.b )

	return circle
end

Doesn’t look like a huge improvement, but it does more than you might think. By separating our code in this way our program can make colors and circles in a wider variety of circumstances.