This is the second installment in our Corona SDK Retro Racing game tutorial. In today’s tutorial, we’ll add to our interface and the game interaction. Read on!
Also available in this series:
- Create a Retro Racing Game - Interface Creation
- Create a Retro Racing Game - Adding Interaction
Where We Left Off. . .
Please be sure to check part 1 of the series to fully understand and prepare for this tutorial.
Step 1: Start Button Listeners
This function adds the necesary listeners to the TitleView buttons.
function startButtonListeners(action) if(action == 'add') then playBtn:addEventListener('tap', showGameView) creditsBtn:addEventListener('tap', showCredits) else playBtn:removeEventListener('tap', showGameView) creditsBtn:removeEventListener('tap', showCredits) end end
Step 2: Show Credits
The credits screen is shown when the user taps the about button. A tap listener is added to the credits view to remove it.
function showCredits:tap(e) playBtn.isVisible = false creditsBtn.isVisible = false creditsView = display.newImage('credits.png', 0, display.contentHeight) lastY = titleBg.y transition.to(titleBg, {time = 300, y = (display.contentHeight * 0.5) - (titleBg.height + 50)}) transition.to(creditsView, {time = 300, y = (display.contentHeight * 0.5) + 35, onComplete = function() creditsView:addEventListener('tap', hideCredits) end}) end
Step 3: Hide Credits
When the credits screen is tapped, it'll be tweened out of the stage and removed.
function hideCredits:tap(e) transition.to(creditsView, {time = 300, y = display.contentHeight + 25, onComplete = function() creditsBtn.isVisible = true playBtn.isVisible = true creditsView:removeEventListener('tap', hideCredits) display.remove(creditsView) creditsView = nil end}) transition.to(titleBg, {time = 300, y = lastY}); end
Step 4: Show the Game View
When the Start button is tapped, the title view is tweened and removed revealing the game view. There are many parts involved in this view, so we'll split them over the next few steps.
function showGameView:tap(e) transition.to(titleView, {time = 300, x = -titleView.height, onComplete = function() startButtonListeners('rmv') display.remove(titleView) titleView = nil end})
Step 5: Place the Game Background
This code places the game background image in the stage.
-- Game Background display.remove(bg) gameBg = display.newImage('gameBg.png')
Step 6: Add the Car
Next, we add the Car image and place it in the center of the stage.
-- Car car = display.newImage('car.png', 90, 412)
Step 7: Create the Highway
This part creates the Highway lines, this image is added twice to create a loop. One is visible on the screen while the other waits in the top part of the stage.
-- Highway lines1 = display.newImage('lines.png', 0, -18) lines2 = display.newImage('lines.png', 0, -558) lines1:setReferencePoint(display.TopLeftReferencePoint) lines2:setReferencePoint(display.TopLeftReferencePoint) obstacles = display.newGroup()
Step 8: Add Text Fields
Now we place three textfields to display the Score, Level, and Speed.
-- TextFields score = display.newText('0', 272, 38, native.systemFont, 17) score:setTextColor(0) level = display.newText('1', 272, 108, native.systemFont, 17) level:setTextColor(0) speed = display.newText('1', 272, 178, native.systemFont, 17) speed:setTextColor(0)
Step 9: Create the Game Controls
Two buttons are added to use as controls for the car: left and right.
-- Direction Buttons leftBtn = display.newImage('button.png', -2, 420) leftBtn.name = 'l' rightBtn = display.newImage('button.png', 260, 420) rightBtn.name = 'r'
Step 10: Car Physics
Now we add the car to the physics engine, this way we can report collisions.
-- Physics physics.addBody(car, 'dynamic') gameListeners('add')
Step 11: Game Listeners
This function adds the necessary listeners to start the game logic.
This is a important part if you try to customize the game. The moveTimer controls the speed of the game. By default it is 100 milliseconds for Level 1, so level 2 may be 200 and so on.
The duration of the game is based in the number of obstacles that are presented in the level; this is defined by the oTimer. Modify the 15 value to create shorter or larger levels.
function gameListeners(action) if(action == 'add') then leftBtn:addEventListener('tap', moveCar) rightBtn:addEventListener('tap', moveCar) moveTimer = timer.performWithDelay(100, update, 0)--level speed oTimer = timer.performWithDelay(1400, addObstacle, 15)--level lenght car:addEventListener('collision', onCollision) else leftBtn:removeEventListener('tap', moveCar) rightBtn:removeEventListener('tap', moveCar) timer.cancel(moveTimer) moveTimer = nil timer.cancel(oTimer) oTimer = nil car:removeEventListener('collision', onCollision) end end
Step 12: Car Movement
This function controls the car. It tests the button pressed and moves the car to the chosen position if available.
function moveCar(e) if(e.target.name == 'l' and car.x ~= 62) then car.x = car.x - 54 elseif(e.target.name == 'r' and car.x ~= 170) then car.x = car.x + 54 end end
Step 13: Add Obstacle
Obstacles are added by a timer based on a randomly calculated position which can be left, center or right. This function create an obstacle, gives it physics and then is added to a Group to make its movement and removal easier.
function addObstacle(e) local rx = positionsTable[math.floor(math.random() * 3) + 1] local o = display.newImage('obstacle.png', rx, -52) physics.addBody(o, 'static') o.isSensor = true obstacles:insert(o) started = true end
Step 14: Move the Highway
The update function is run by a timer to create the brick-by-brick effect. The next code loops the highway lines.
function update(e) -- Move Highway lines1.y = lines1.y + 16 lines2.y = lines2.y + 16 -- Reset highway position if(lines1.y >= 522) then lines1.y = -558 elseif(lines2.y >= 522) then lines2.y = -558 end
Step 15: Move Obstacles
This lines move the obstacles and remove the ones that are no longer visible. The score increases each time the car doesn't hit an obstacle.
for i = 1, obstacles.numChildren do -- Move Obstacles if(obstacles[i] ~= nil) then obstacles[i].y = obstacles[i].y + 16 end -- Remove offstage obstacles if(obstacles[i] ~= nil and obstacles[i].y >= display.contentHeight + 26) then display.remove(obstacles[i]) score.text = tostring(tonumber(score.text) + 50) end end
Step 16: Level Completion
Here we check if all the obstacles defined are already out of the stage and call a win alert if true.
-- Check for level complete if(started and obstacles.numChildren == 0) then alert() end end
Step 17: Adding an Alert
The Collision function checks if the car is hit by an obstacle and calls a lose alert if true.
function onCollision(e) alert('lose') end function alert(msg) gameListeners('rmv') if(msg == 'lose') then alert = display.newImage('alert.png', 52, 229.5) else alert = display.newImage('complete.png', 18, 229.5) end transition.from(alert, {time = 300, xScale = 0.5, yScale = 0.5}) physics.stop() end
Step 18: Call the Main Function
In order to start the game, the Main function needs to be called. With the above code in place, we'll do that here:
Main()
Step 19: Add a Loading Screen
The Default.png file is an image that will be displayed right when you start the application while iOS loads the basic data to show the Main Screen. Add this image to your project source folder.
Step 20: Add an Icon
Using the graphics you created before you can now create a nice and good looking icon. The icon size for
the non-retina iPhone icon is 57x57px, but the retina version is 114x114px and the iTunes store requires a 512x512px version. I suggest creating the 512x512 version first and then scaling down for the other sizes.
It doesn't need to have the rounded corners or the transparent glare, iTunes and the iPhone will do that for you.
Step 21: Testing in the Simulator
It's time to do the final test. Open the Corona Simulator, browse to your project folder, and then click open. If everything works as expected, you are ready for the final step!
Step 22: Build
In the Corona Simulator go to File > Build and select your target device. Fill the required data and click build. Wait a few seconds and your app will be ready for device testing and/or submission for distribution!
Conclusion
Experiment with the final result and try to make your custom version of the game!
I hope you liked this tutorial series and found it helpful. Thank you for reading!
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.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post