Cloud Buster
Updated on June 26th, 2021 at 1:13 am
What is it?
This was a game that I created in my mobile development class at my Junior College. The app was made with the Corona SDK and programmed in Lua. The concept of the game is based on a popular game called “Flappy Bird”. You play as an airplane that you can control by touching anywhere on the screen. The longer you touch the screen, the longer the plane flies up. As you release your finger from the screen, the plane falls down.
The goal of the game is to run into as many white clouds as you can. There is no end game screen, instead, the goal is to raise your score as high as possible. Your plane only has three lives and flying into gray clouds drops lives. After losing all three lives, the game is over and your score drops to 0. However, you are able to gain lives back by flying into the rare and mysterious rainbow clouds.

What does it do?
This app was designed to be a 2k mobile game. It was created with the Corona SDK and as such, can be built for iOS and Android devices. It may be possible to build the game for macOS and Windows as well.
How does it work?
Games made with the Corona SDK are primarily made of Lua Scripts. Each script would generally equate to a single scene or level within the game. Since this game only has a single scene, there is only one script. The rest of the files in the project are made up of images, icons, backgrounds, and sprites.
main.lua
----------------------------------------------------------------------------------------- -- Fly Game 2 -- Ryan Bains-Jordan -- -- Main ----------------------------------------------------------------------------------------- -- Status Bar display.setStatusBar( display.HiddenStatusBar ) -- Variable Declarations local w = display.contentWidth local h = display.contentHeight local bg = {} local plane = {} local cloud = {} local cloudSheetWInst local cloudSheetDInst local cloudSheetRInst local touched = false -- Has the screen been touched (Used in screenTouched()) local hits = 0 -- Counts the clouds intercepted by plane (Used in updateScore()) local hitsText local lives = {} local splash = {} local rButton = nil local rButtonText = "" ----------------------------------------------------------------------------------------- -- Game Initiation Function ----------------------------------------------------------------------------------------- function initGame() -- Background bg = display.newImageRect( "background.png", w * 4, h ) bg.starting = 660 bg.ending = -250 bg.x = bg.starting bg.y = h / 2 -- Plane plane = display.newImageRect( "plane.png", 77, 43 ) plane.x = 75 plane.y = h-100 plane.velocity = 0 plane.acceleration = 0.5 / 2 plane.bounce = 0.5 plane.sound = audio.loadSound( "plane.wav" ) plane.skid = audio.loadSound("skid.wav") plane.lives = 3 -- Lives lives.life1 = display.newImage( "plane.png", 50, 20 ) lives.life2 = display.newImage( "plane.png", 100, 20 ) lives.life3 = display.newImage( "plane.png", 150, 20 ) lives.life1:scale( .2, .2) lives.life2:scale( .2, .2) lives.life3:scale( .2, .2) lives.score = {lives.life1, lives.life2, lives.life3} -- Text Color local color = { hightlight = { r=0.6, g=0.4, b=0.2 }, shadow = { r=0.3, g=0.3, b=0.3 } } -- Hit Score hitsText = display.newEmbossedText( "", w/2, 100, native.systemFont, 25 ) hitsText:setFillColor( 1, .804, 0 ) hitsText:setEmbossColor( color ) -- White Clouds for i = 1, 3 do cloud[i] = display.newImageRect("cloud.png", 75, 50) cloud[i].x = -100 + (i * 200) cloud[i].y = 100 end -- Dark Clouds cloud[4] = display.newImageRect("dark_cloud.png", 75, 50) cloud[4].x = -100 -- Rainbow Clouds cloud[5] = display.newImageRect( "rain_cloud.png", 75, 50 ) cloud[5].x = -100 -- Cloud Initiations cloud.white = { animation=false } cloud.dark = { visable=false, aniamation=false } cloud.rain = { visable=false, animation=false } cloud.sound = audio.loadSound( "poof.wav" ) -- Cloud Animation cloudSheet = graphics.newImageSheet( "cloud_sheet.png", { width=128, height=128, numFrames=48 } ) cloudSheetWInst = display.newSprite( cloudSheet, { start=1, count=16, time=500, loopCount=1 } ) cloudSheetDInst = display.newSprite( cloudSheet, { start=17, count=16, time=500, loopCount=1 } ) cloudSheetRInst = display.newSprite( cloudSheet, { start=33, count=16, time=500, loopCount=1 } ) cloudSheetWInst.x = -100 cloudSheetWInst.y = -100 cloudSheetDInst.x = -100 cloudSheetDInst.y = -100 cloudSheetRInst.x = -100 cloudSheetRInst.y = -100 -- Game Over Screen splash.screen = display.newRoundedRect( w/2, h/2, w-100, h-100, 25 ) splash.screen:setFillColor( 0.5, 0.5, 0.5, 0.9 ) splash.screen.isVisible = false splash.header = display.newEmbossedText( "Game Over", w/2, h/2-100, native.systemFont, 30 ) splash.header:setFillColor( 1, 0.8, 0 ) splash.header.isVisible = false splash.score = display.newEmbossedText( "Your score was", w/2, h/2-50, native.systemFont, 20 ) splash.score:setFillColor( 1, 0.8, 0 ) splash.score.isVisible = false splash.hits = display.newEmbossedText( "", w/2, h/2, native.systemFont, 25 ) splash.hits:setFillColor( 1, 0.8, 0 ) splash.hits.isVisible = false -- Reset Button rButton = display.newRoundedRect( w/2, h/2+100, 100, 30, 10 ) rButton.strokeWidth = 3 rButton:setFillColor( 1, 0.8, 0 ) rButton:setStrokeColor( 0.6, 0.4, 0.2 ) rButton.isVisible = false rButtonText = display.newEmbossedText( "Reset", rButton.x, rButton.y, native.systemFont, 15 ) rButtonText:setFillColor( 0.6, 0.4, 0.2 ) rButtonText.isVisible = false -- Reset the Score Function function rButton:tap( event ) plane.y = h-100 plane.lives = 3 hits = 0 updateScore() hitsText.isVisible = true displayLives() splash.screen.isVisible = false splash.header.isVisible = false splash.score.isVisible = false splash.hits.isVisible = false rButton.isVisible = false rButtonText.isVisible = false Runtime:addEventListener( "enterFrame", newFrame ) Runtime:addEventListener( "touch", screenTouched ) end -- Install the animation event listeners Runtime:addEventListener( "enterFrame", newFrame ) Runtime:addEventListener( "touch", screenTouched ) rButton:addEventListener( "tap", rButton ) end ----------------------------------------------------------------------------------------- -- Main Functions ----------------------------------------------------------------------------------------- -- Animate Background function bgAnimate() bg.x = bg.x - 5 if bg.x <= bg.ending then bg.x = bg.starting end end -- Randomise height of clouds function randomHeight( i ) local rnd = math.random( 50, 250 ) cloud[i].y = rnd end -- Calculate Velocity and Acceleration of Fall function falling() -- Move the plane according to its current velocity plane.y = plane.y + plane.velocity -- If the plane passed the bottom during this frame, make it bounce if (plane.y > h - 100 ) then if ( plane.velocity > 3 ) then audio.play( plane.skid, { channel=6, loops=0 } ) end plane.y = plane.y - plane.velocity -- Undo the downward movement that went past the bottom plane.velocity = - plane.velocity * plane.bounce -- Reverse the downward speed and apply bounce factor end -- Change the current velocity over time by applying the acceleration (gravity) plane.velocity = plane.velocity + plane.acceleration end -- Calculate Velocity of Climb function flying() plane.y = plane.y - 5 plane.velocity = 0 plane.acceleration = 0.5 / 2 end -- Plane moving event function screenTouched( event ) if event.phase == "began" or event.phase == "moved" then touched = true else touched = false end if event.phase == "began" then audio.play( plane.sound , { channel=5, loops=-1 }) end if event.phase == "ended" then audio.stop( 5 ) end end -- Check Collision function checkCollision() local collision = false plane.ftx = plane.x + 38 -- Plane Front Top X Position plane.fty = plane.y - 21 -- Plane Front Top Y Position plane.fbx = plane.x + 38 -- Plane Front Bottom X Position plane.fby = plane.y + 21 -- Plane Front Bottom Y Position for i = 1, table.getn(cloud) do cloud.ftx = cloud[i].x - 37 -- Cloud Front Top X Position cloud.fty = cloud[i].y - 25 -- Cloud Front Top Y Position cloud.fbx = cloud[i].x - 37 -- Cloud Front Bottom X Position cloud.fby = cloud[i].y + 25 -- Cloud Front Bottom Y Position if plane.ftx > cloud.ftx - 5 and plane.ftx < cloud.fbx + 5 then if plane.fby > cloud.fty and plane.fby < cloud.fby then -- If bottom front of plane hits cloud collision = true elseif plane.fty > cloud.fty and plane.fty < cloud.fby then -- If top front of plane hits cloud collision = true else collision = false end if collision == true then if i ~= 4 then hits = hits + 1 if i == 5 and plane.lives < 3 then plane.lives = plane.lives + 1 displayLives() end else if plane.lives > 0 then plane.lives = plane.lives - 1 if plane.lives == 0 then endGame() end displayLives() end end animateCloud(i) cloud[i].x = math.random( 400, 800 ) randomHeight(i) audio.play( cloud.sound ) updateScore() collision = false end end end end --Animate the Cloud function animateCloud(i) -- Dark Cloud if i == 4 then cloud.dark.animation = true cloudSheetDInst.x = cloud[i].x cloudSheetDInst.y = cloud[i].y cloudSheetDInst:play() -- Rain Cloud elseif i == 5 then cloud.rain.animation = true cloudSheetRInst.x = cloud[i].x cloudSheetRInst.y = cloud[i].y cloudSheetRInst:play() --White Cloud else cloud.white.animation = true cloudSheetWInst.x = cloud[i].x cloudSheetWInst.y = cloud[i].y cloudSheetWInst:play() end end -- Update the Score function updateScore() hitsText:setText(hits) splash.hits:setText(hits) end -- Dispaly the Planes Lives function displayLives() for i = 1, 3 do if i <= plane.lives then lives.score[i].isVisible = true else lives.score[i].isVisible = false end end end -- Game Over Screen function endGame() splash.screen.isVisible = true splash.header.isVisible = true splash.score.isVisible = true splash.hits.isVisible = true hitsText.isVisible = false timer.performWithDelay( 1000, buttonVisability ) --Delay Buttons Visability Runtime:removeEventListener( "enterFrame", newFrame ) Runtime:removeEventListener( "touch", screenTouched ) audio.stop( 5 ) touched = false end -- Button Visability function buttonVisability() rButton.isVisible = true rButtonText.isVisible = true end ----------------------------------------------------------------------------------------- -- Animation ----------------------------------------------------------------------------------------- function newFrame() bgAnimate() if touched == false then falling() end if touched == true then flying() end -- Draw White Clouds for i = 1, 3 do cloud[i].x = cloud[i].x - 3 if cloud[i].x <= w - 380 then cloud[i].x = w + 380 randomHeight(i) end end -- Draw Dark Clouds if cloud.dark.visable == false then local dc = math.random( 200 ) -- Larger = More Rare if dc == 50 then -- Any number cloud.dark.visable = true randomHeight(4) end end -- Move the Dark Cloud if it Exists if cloud.dark.visable == true then cloud[4].x = cloud[4].x - 2 if cloud[4].x <= w - 380 then cloud[4].x = w + 380 cloud.dark.visable = false end end -- Draw Rainbow Clouds if cloud.rain.visable == false then local rc = math.random( 800 ) -- Larger = More Rare if rc == 50 then -- Any number cloud.rain.visable = true randomHeight(5) end end -- Move the Rainbow Cloud if it Exists if cloud.rain.visable == true then cloud[5].x = cloud[5].x - 5 if cloud[5].x <= w - 380 then cloud[5].x = w + 380 cloud.rain.visable = false end end -- Move White Cloud Animation if cloud.white.animation == true then cloudSheetWInst.x = cloudSheetWInst.x - 3 if cloudSheetWInst.x <= -380 then cloud.white.animation = false end end -- Move Dark Cloud Animation if cloud.dark.animation == true then cloudSheetDInst.x = cloudSheetDInst.x - 2 if cloudSheetDInst.x <= -380 then cloud.dark.animation = false end end -- Move Rainbow Cloud Animation if cloud.rain.animation == true then cloudSheetRInst.x = cloudSheetRInst.x - 3 if cloudSheetRInst.x <= -380 then cloud.rain.animation = false end end checkCollision() end ----------------------------------------------------------------------------------------- -- Game Initiation ----------------------------------------------------------------------------------------- initGame()