Part 3: Corona SDK: A Simple Race game

If you have been reading and coding along, you would now have a start screen and a game background with a start time counter from 3 till 0. In Part 3, and final part, we will program the actual gameplay of the little game. In case you missed Part 1 or 2, please navigate to these tutorials if you like:

Part 1
Part 2

In case you are looking for the complete source code, the post of Part 1 has on the bottom a download link for the complete package.

In this post we will set up the following functions
- Create and spawn cars on the screen
- Touch events when a user taps the car
- The scoring
- Crashing of cars in the wall

First set the following variables as global:

local touchCar
local createCar
local carArray
local BLUE_CAR = 1
local wall
local car
local hitWall

Now we can start with the first function createCar().

In this function we create cars based on a random selection from a defined Array. In total we have 4 different cars, each having their own color. #carArray determines the number of the cars in the Array, which is in our case 4. Each time createCar() is called a new car is created based on a random number of #carArray (so a number between 0 – 4). The index of which image of a car needs to be created is randomly selected and stored in the variable car.

We position the car initially off the screen (x=-200) and y based on a random value over the complete height of the screen. This way it is still a bit of suprise from where the car will be spawned. The xScale and yScale and rotate has been used to position the car in a better way. If you need this or not, depends on your art work.

We will say later in the scoring that a blue car get more points than a non-blue car. This means we need to be able to access this value later, hence that a parameter is added to car.type = carType.

Finally we use transition.to to move the car along the screen. As you can see the car moves towards the wall on the complete right, when the user doesn’t tap the car in time the onComplete function hitWall will be called.

function createCar()
	carArray = { "carblue.png", "cargreen.png",  "carred.png",  "caryellow.png"  }
	carType = math.random (#carArray )    
   car = display.newImage( carArray [ carType ] )
	
	car.x = -200
	car.y = math.random (0, display.contentHeight)
	car.xScale = 0.2
	car.yScale = 0.2
	car:rotate (90)
	car.type = carType
	
	car.moves = transition.to (car, {time = 3000,  x=display.contentWidth-30 , y=math.random(0,display.contentHeight), onComplete = hitWall } )
	car:addEventListener ( "tap", touchCar )
	
	return car
end

In the next function we will determine what need to happen when a user taps the spawned car. First when a car is tapped the car kinda brakes so we load a sound file. Next, I thought it would be nice that the car really visualize the braking, and let say the car brakes quite suddenly so a slip occurs. We can do this by easily rotating the car. Another important note is that we call transition.cancel as the car will not reach the wall and thus no OnComplete (hitWall) needs to be called anymore.

When the blue car is touched we want to reward the user with a score of 15 otherwise a score of 5. We use .type to access the type property of the spawned car and check against BLUE_CAR. BLUE_CAR has been set as 1, referring tot the first index of the carArray.

Finally we want to remove the car of the screen with a small delay and update the score.

function touchCar(event)
	local cartouched = event.target
	transition.cancel ( event.target.moves )
	audio.play(brake)
	cartouched:rotate (370)
			
	if  cartouched.type == BLUE_CAR  then
		score = score + 15
		else score = score +5
	end
	scorelabel.text = "Score: ".. score 
		local function removeCar()
			display.remove(cartouched)
		end	
	timer.performWithDelay(600, removeCar)
	
	createCar()
end

Next up is the function hitWall. Meaning what needs to happen when the user does not tap the car in time and crashes into the wall.

We want that the user has the feeling that the wall has been damaged, so therefore we scale the wall a little bit, after the hit we need to set the wall back to its initial scales (local function resetWall). When the car crashes into the wall we rotate car randomly to make it more look like a real crash and we scale the car as nice side effect. We play the crash sound and run the lifeCount() function to see if the user has crashed 3 times or less. The live were set in the createGame() function as wall.crashnumer = 3 (see part 2).

When the number of wall.crashnumber are lager than 0, we spawn a new car.

function hitWall(obj)
	
		local function resetWall()
			wall.xScale =1
			wall.yScale = 1
		
				local function removeCar()
					display.remove(obj)
				end
		timer.performWithDelay ( 1200, removeCar )
		end
		car.xScale =0.22
		car.yScale = 0.22
		car:rotate (math.random (-90, 90))
		lifeCount()
		audio.play(crash)
		
		transition.to ( wall, { time=200, xScale=1.1, yScale=1.1, alpha=1, onComplete = resetWall } )
		
		if wall.crashnumber > 0 then	
			createCar()
		end
end

The last peace is the function to check if the user has no lives left and display a game over text. This is pretty straightforward

function lifeCount()
	wall.crashnumber = wall.crashnumber  - 1
	if wall.crashnumber <1 then
		gameovertext = display.newText("Game Over", cWidth-80, cHeight, "Helvetica", 24)
		timer.performWithDelay ( 1500, createTitleScreen )
	end
end

The complete code we used in part 3 is now:

function createCar()
	carArray = { "carblue.png", "cargreen.png",  "carred.png",  "caryellow.png"  }
	carType = math.random (#carArray )    
   car = display.newImage( carArray [ carType ] )
	
	car.x = -200
	car.y = math.random (0, display.contentHeight)
	car.xScale = 0.2
	car.yScale = 0.2
	car:rotate (90)
	car.type = carType
	
	car.moves = transition.to (car, {time = 3000,  x=display.contentWidth-30 , y=math.random(0,display.contentHeight), onComplete = hitWall } )
	car:addEventListener ( "tap", touchCar )
	
	return car
end


function touchCar(event)
	local cartouched = event.target
	transition.cancel ( event.target.moves )
	audio.play(brake)
	cartouched:rotate (370)
			
	if  cartouched.type == BLUE_CAR  then
		score = score + 15
		else score = score +5
	end
	scorelabel.text = "Score: ".. score 
		local function removeCar()
			display.remove(cartouched)
		end	
	timer.performWithDelay(600, removeCar)
	
	createCar()
end

function hitWall(obj)
	
		local function resetWall()
			wall.xScale =1
			wall.yScale = 1
		
				local function removeCar()
					display.remove(obj)
				end
		timer.performWithDelay ( 1200, removeCar )
		end
		car.xScale =0.22
		car.yScale = 0.22
		car:rotate (math.random (-90, 90))
		lifeCount()
		audio.play(crash)
		
		transition.to ( wall, { time=200, xScale=1.1, yScale=1.1, alpha=1, onComplete = resetWall } )
		
		if wall.crashnumber > 0 then	
			createCar()
		end
end

function lifeCount()
	wall.crashnumber = wall.crashnumber  - 1
	if wall.crashnumber <1 then
		gameovertext = display.newText("Game Over", cWidth-80, cHeight, "Helvetica", 24)
		timer.performWithDelay ( 1500, createTitleScreen )
	end
end

You have reached the end of this simple car game tutorial. This is not a type of game you can publish in the app stores, but I hope some of the functions are useful in your game programming.

In case you have missed it and are looking for the complete source code, please visit part 1.

1 Response

Leave a Reply to Kylie Brown Cancel reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*