Don't like ads? PRO users don't see any ads ;-)
Guest

Ghost Vs Mosters

By: a guest on Aug 1st, 2012  |  syntax: Lua  |  size: 48.34 KB  |  hits: 23  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. --
  2. -- Abstract: Ghosts Vs Monsters sample project
  3. -- Designed and created by Jonathan and Biffy Beebe of Beebe Games exclusively for Ansca, Inc.
  4. -- http://beebegamesonline.appspot.com/
  5.  
  6. -- (This is easiest to play on iPad or other large devices, but should work on all iOS and Android devices)
  7. --
  8. -- Version: 1.1
  9. --
  10. -- Sample code is MIT licensed, see http://developer.anscamobile.com/code/license
  11. -- Copyright (C) 2010 ANSCA Inc. All Rights Reserved.
  12.  
  13. module(..., package.seeall)
  14.  
  15. --***********************************************************************************************--
  16. --***********************************************************************************************--
  17.  
  18. -- LEVEL MODULE
  19.  
  20. -- To create a new level, change "MODULE-SPECIFIC VARIABLES" (below) and also the
  21. -- createLevel() function. Everything else should be identical between level modules.
  22.  
  23. --***********************************************************************************************--
  24. --***********************************************************************************************--
  25.  
  26.  
  27. -- Main function - MUST return a display.newGroup()
  28. function new()
  29.        
  30.         local hudGroup = display.newGroup()
  31.        
  32.         local gameGroup = display.newGroup()
  33.         gameGroup.x = -480
  34.        
  35.         local trailGroup = display.newGroup()
  36.         local dotTimer
  37.        
  38.         local levelGroup = display.newGroup()
  39.        
  40.         -- MODULE-SPECIFIC VARIABLES
  41.         local backgroundFilename1 = "altbackground1.png"
  42.         local backgroundFilename2 = "altbackground2.png"
  43.        
  44.         -- EXTERNAL MODULES / LIBRARIES
  45.        
  46.         local movieclip = movieclip --require( "movieclip" )
  47.         local physics = require "physics"
  48.         local ui = ui --require("ui")
  49.         --local facebook = require "facebook"
  50.        
  51.         local mCeil = math.ceil
  52.         local mAtan2 = math.atan2
  53.         local mPi = math.pi
  54.         local mSqrt = math.sqrt
  55.        
  56.         -- OBJECTS
  57.        
  58.         local backgroundImage1
  59.         local backgroundImage2
  60.         local clouds1
  61.         local clouds2
  62.         local clouds3
  63.         local clouds4
  64.         local groundLight1
  65.         local groundObject1
  66.         local groundObject2
  67.         local shotOrb
  68.         local shotArrow
  69.         local blastGlow
  70.         local ghostObject
  71.         local poofObject
  72.         local greenPoof; local poofTween
  73.        
  74.         local life1; local life2; local life3; local life4
  75.         local scoreText; local bestScoreText
  76.         local continueText; local continueTimer
  77.         local pauseMenuBtn; local pauseBtn; local pauseShade
  78.        
  79.         -- VARIABLES
  80.        
  81.         local gameIsActive = false
  82.         local waitingForNewRound
  83.         local restartTimer
  84.         local ghostTween
  85.         local screenPosition = "left"   --> "left" or "right"
  86.         local canSwipe = true
  87.         local swipeTween
  88.         local gameLives = 4
  89.         local gameScore = 0
  90.         local bestScore
  91.         local monsterCount
  92.        
  93.         -- LEVEL SETTINGS
  94.        
  95.         local restartModule
  96.         local nextModule
  97.         local woodDensity = 2.0
  98.         local vPlankShape = { -6,-48, 6,-48, 6,48, -6,48 }
  99.         local hPlankShape = { -48,-6, 48,-6, 48,6, -48,6 }
  100.         local stoneDensity = 5.0
  101.         local vSlabShape = { -12,-26, 12,-26, 12,26, -12,26 }
  102.         local tombDensity = 5.5
  103.         local tombShape = { -18,-21, 18,-21, 18,21, -18,21 }
  104.         local monsterDensity = 1.0
  105.         local monsterShape = { -12,-13, 12,-13, 12,13, -12,13 }
  106.        
  107.         -- AUDIO
  108.        
  109.         local tapSound = audio.loadSound( "tapsound.wav" )
  110.         local blastOffSound = audio.loadSound( "blastoff.wav" )
  111.         local ghostPoofSound = audio.loadSound( "ghostpoof.wav" )
  112.         local monsterPoofSound = audio.loadSound( "monsterpoof.wav" )
  113.         local impactSound = audio.loadSound( "impact.wav" )
  114.         local weeSound = audio.loadSound( "wee.wav" )
  115.         local newRoundSound = audio.loadSound( "newround.wav" )
  116.         local youWinSound = audio.loadSound( "youwin.wav" )
  117.         local youLoseSound = audio.loadSound( "youlose.wav" )
  118.        
  119.         --***************************************************
  120.  
  121.         -- saveValue() --> used for saving high score, etc.
  122.        
  123.         --***************************************************
  124.         local saveValue = function( strFilename, strValue )
  125.                 -- will save specified value to specified file
  126.                 local theFile = strFilename
  127.                 local theValue = strValue
  128.                
  129.                 local path = system.pathForFile( theFile, system.DocumentsDirectory )
  130.                
  131.                 -- io.open opens a file at path. returns nil if no file found
  132.                 local file = io.open( path, "w+" )
  133.                 if file then
  134.                    -- write game score to the text file
  135.                    file:write( theValue )
  136.                    io.close( file )
  137.                 end
  138.         end
  139.        
  140.         --***************************************************
  141.  
  142.         -- loadValue() --> load saved value from file (returns loaded value as string)
  143.        
  144.         --***************************************************
  145.         local loadValue = function( strFilename )
  146.                 -- will load specified file, or create new file if it doesn't exist
  147.                
  148.                 local theFile = strFilename
  149.                
  150.                 local path = system.pathForFile( theFile, system.DocumentsDirectory )
  151.                
  152.                 -- io.open opens a file at path. returns nil if no file found
  153.                 local file = io.open( path, "r" )
  154.                 if file then
  155.                    -- read all contents of file into a string
  156.                    local contents = file:read( "*a" )
  157.                    io.close( file )
  158.                    return contents
  159.                 else
  160.                    -- create file b/c it doesn't exist yet
  161.                    file = io.open( path, "w" )
  162.                    file:write( "0" )
  163.                    io.close( file )
  164.                    return "0"
  165.                 end
  166.         end
  167.        
  168.         local startNewRound = function()
  169.                 if ghostObject then
  170.                        
  171.                         local activateRound = function()
  172.                                
  173.                                 canSwipe = true
  174.                                 waitingForNewRound = false
  175.                                                
  176.                                 if restartTimer then
  177.                                         timer.cancel( restartTimer )
  178.                                 end
  179.                                
  180.                                 groundLight1:toFront()
  181.                                 groundObject1:toFront()
  182.                                 groundObject2:toFront()
  183.                                 ghostObject.x = 150; --ghostObject.y = 195
  184.                                 ghostObject.y = 300;
  185.                                 ghostObject:stopAtFrame( 1 )
  186.                                 ghostObject.rotation = 0
  187.                                 ghostObject.isVisible = true
  188.                                 ghostObject.isBodyActive = true
  189.                                
  190.                                 audio.play( newRoundSound )
  191.                                
  192.                                 local ghostLoaded = function()
  193.                                        
  194.                                         gameIsActive = true
  195.                                         ghostObject.inAir = false
  196.                                         ghostObject.isHit = false
  197.                                         ghostObject:toFront()
  198.                                        
  199.                                         ghostObject.bodyType = "static"
  200.                                        
  201.                                         -- Show the pause button
  202.                                         pauseBtn.isVisible = true
  203.                                         pauseBtn.isActive = true
  204.                                        
  205.                                         -- START up and down animation
  206.                                         if ghostTween then
  207.                                                 transition.cancel( ghostTween )
  208.                                         end
  209.                                        
  210.                                         local function ghostAnimation()
  211.                                                 local animUp = function()
  212.                                                         if ghostObject.inAir or shotOrb.isVisible then
  213.                                                                 transition.cancel( ghostTween )
  214.                                                         else
  215.                                                                 ghostTween = transition.to( ghostObject, { time=375, y=190, onComplete=ghostAnimation })
  216.                                                         end
  217.                                                 end
  218.                                                
  219.                                                 if ghostObject.inAir or shotOrb.isVisible then
  220.                                                         transition.cancel( ghostTween )
  221.                                                 else
  222.                                                         ghostTween = transition.to( ghostObject, { time=375, y=200, onComplete=animUp })
  223.                                                 end
  224.                                         end
  225.                                        
  226.                                         ghostTween = transition.to( ghostObject, { time=375, y=190, onComplete=ghostAnimation })
  227.                                        
  228.                                         -- END up and down animation
  229.                                 end
  230.                                
  231.                                 transition.to( ghostObject, { time=1000, y=195, onComplete=ghostLoaded } )
  232.                         end
  233.                        
  234.                         -- reset camera
  235.                         if gameGroup.x < 0 then
  236.                                 transition.to( gameGroup, { time=1000, x=0, transition=easing.inOutExpo, onComplete=activateRound } )
  237.                         else
  238.                                 gameGroup.x = 0
  239.                                 activateRound()
  240.                         end
  241.                 end
  242.         end
  243.        
  244.         local comma_value = function(amount)
  245.                 local formatted = amount
  246.                         while true do  
  247.                         formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
  248.                         if (k==0) then
  249.                                 break
  250.                         end
  251.                 end
  252.                
  253.                 return formatted
  254.         end
  255.        
  256.         local setScore = function( scoreNum )
  257.                 local newScore = scoreNum
  258.                
  259.                 gameScore = newScore
  260.                
  261.                 if gameScore < 0 then gameScore = 0; end
  262.                
  263.                 scoreText.text = comma_value(gameScore)
  264.                 scoreText.xScale = 0.5; scoreText.yScale = 0.5  --> for clear retina display text
  265.                 scoreText.x = (480 - (scoreText.contentWidth * 0.5)) - 15
  266.                 scoreText.y = 20
  267.         end
  268.        
  269.         local callGameOver = function( isWin )
  270.                
  271.                 local isWin = isWin
  272.                
  273.                 if isWin == "yes" then
  274.                         audio.play( youWinSound )
  275.                 else
  276.                         audio.play( youLoseSound )
  277.                 end
  278.                
  279.                 gameIsActive = false    --> temporarily disable gameplay touches, enterFrame listener, etc.
  280.                 physics.pause()
  281.                
  282.                 -- Make sure pause button is hidden/inactive
  283.                 pauseBtn.isVisible = false
  284.                 pauseBtn.isActive = false
  285.                
  286.                 if continueTimer then timer.cancel( continueTimer ); end
  287.                 continueText.isVisible = false
  288.                
  289.                 -- Create all game over objects and insert them into the HUD group
  290.                
  291.                 -- SHADE
  292.                 local shadeRect = display.newRect( 0, 0, 480, 320 )
  293.                 shadeRect:setFillColor( 0, 0, 0, 255 )
  294.                 shadeRect.alpha = 0
  295.                
  296.                
  297.                 -- GAME OVER WINDOW
  298.                 local gameOverDisplay
  299.                
  300.                 if isWin == "yes" then
  301.                         gameOverDisplay = display.newImageRect( "youwin.png", 390, 154 )
  302.                        
  303.                         -- Give score bonus depending on how many ghosts left
  304.                         local ghostBonus = gameLives * 20000
  305.                         local newScore = gameScore + ghostBonus
  306.                         setScore( newScore )
  307.                        
  308.                 else
  309.                         gameOverDisplay = display.newImageRect( "youlose.png", 390, 154 )
  310.                 end
  311.                
  312.                 gameOverDisplay.x = 240; gameOverDisplay.y = 165
  313.                 gameOverDisplay.alpha = 0
  314.                
  315.                 -- MENU BUTTON
  316.                 local onMenuTouch = function( event )
  317.                         if event.phase == "release" then
  318.                                 audio.play( tapSound )
  319.                                 director:changeScene( "loadmainmenu" )
  320.                         end
  321.                 end
  322.                
  323.                 local menuBtn = ui.newButton{
  324.                         defaultSrc = "menubtn.png",
  325.                         defaultX = 60,
  326.                         defaultY = 60,
  327.                         overSrc = "menubtn-over.png",
  328.                         overX = 60,
  329.                         overY = 60,
  330.                         onEvent = onMenuTouch,
  331.                         id = "MenuButton",
  332.                         text = "",
  333.                         font = "Helvetica",
  334.                         textColor = { 255, 255, 255, 255 },
  335.                         size = 16,
  336.                         emboss = false
  337.                 }
  338.                
  339.                 if isWin == "yes" then
  340.                         menuBtn.x = 227
  341.                 else
  342.                         menuBtn.x = 266
  343.                 end
  344.                
  345.                 menuBtn.y = 186
  346.                 menuBtn.alpha = 0
  347.                
  348.                 -- RESTART BUTTON
  349.                 local onRestartTouch = function( event )
  350.                         if event.phase == "release" then
  351.                                 audio.play( tapSound )
  352.                                 local theModule = "load" .. restartModule
  353.                                 director:changeScene( theModule )
  354.                         end
  355.                 end
  356.                
  357.                 local restartBtn = ui.newButton{
  358.                         defaultSrc = "restartbtn.png",
  359.                         defaultX = 60,
  360.                         defaultY = 60,
  361.                         overSrc = "restartbtn-over.png",
  362.                         overX = 60,
  363.                         overY = 60,
  364.                         onEvent = onRestartTouch,
  365.                         id = "RestartButton",
  366.                         text = "",
  367.                         font = "Helvetica",
  368.                         textColor = { 255, 255, 255, 255 },
  369.                         size = 16,
  370.                         emboss = false
  371.                 }
  372.                
  373.                 restartBtn.x = menuBtn.x + 72; restartBtn.y = 186
  374.                 restartBtn.alpha = 0
  375.                
  376.                 -- NEXT BUTTON
  377.                 local onNextTouch = function( event )
  378.                         if event.phase == "release" then
  379.                                 audio.play( tapSound )
  380.                                 local theModule = "load" .. nextModule
  381.                                 director:changeScene( theModule )
  382.                         end
  383.                 end
  384.                
  385.                 local nextBtn = ui.newButton{
  386.                         defaultSrc = "nextlevelbtn.png",
  387.                         defaultX = 60,
  388.                         defaultY = 60,
  389.                         overSrc = "nextlevelbtn-over.png",
  390.                         overX = 60,
  391.                         overY = 60,
  392.                         onEvent = onNextTouch,
  393.                         id = "NextButton",
  394.                         text = "",
  395.                         font = "Helvetica",
  396.                         textColor = { 255, 255, 255, 255 },
  397.                         size = 16,
  398.                         emboss = false
  399.                 }
  400.                
  401.                 nextBtn.x = restartBtn.x + 72; nextBtn.y = 186
  402.                 nextBtn.alpha = 0
  403.                 if isWin ~= "yes" then nextBtn.isVisible = false; end
  404.                
  405.                 -- OPENFEINT BUTTON
  406.                 local onOFTouch = function( event )
  407.                         if event.phase == "release" then
  408.                                 audio.play( tapSound )
  409.                                 -- Launch OpenFeint Leaderboards Panel:
  410.                                 --openfeint.launchDashboard("leaderboards")
  411.                                
  412.                         end
  413.                 end
  414.                
  415.                 local ofBtn = ui.newButton{
  416.                         defaultSrc = "openfeintbtn.png",
  417.                         defaultX = 168,
  418.                         defaultY = 40,
  419.                         overSrc = "openfeintbtn-over.png",
  420.                         overX = 168,
  421.                         overY = 40,
  422.                         onEvent = onOFTouch,
  423.                         id = "OpenfeintButton",
  424.                         text = "",
  425.                         font = "Helvetica",
  426.                         textColor = { 255, 255, 255, 255 },
  427.                         size = 16,
  428.                         emboss = false
  429.                 }
  430.                
  431.                 ofBtn.x = 168; ofBtn.y = 110
  432.                 ofBtn.alpha = 0
  433.                
  434.                 local fbBtn
  435.                
  436.                 -- FACEBOOK BUTTON
  437.                 local onFBTouch = function( event )
  438.                         if event.phase == "release" and fbBtn.isActive then
  439.                                 audio.play( tapSound )
  440.                                
  441.                                 -- Code to Post Status to Facebook (don't forget the 'require "facebook"' line at top of module)
  442.                                 -- The Code below is fully functional as long as you replace the fbAppID var with valid app ID.
  443.                                
  444.                                 --[[
  445.                                 local fbAppID = "1234567890"    --> (string) Your FB App ID from facebook developer's panel
  446.                                
  447.                                 local facebookListener = function( event )
  448.                                         if ( "session" == event.type ) then
  449.                                                 -- upon successful login, update their status
  450.                                                 if ( "login" == event.phase ) then
  451.                                                        
  452.                                                         local scoreToPost = comma_value(gameScore)
  453.                                                        
  454.                                                         local statusUpdate = "just scored a " .. gameScore .. " on Ghosts v.s Monsters!"
  455.                                                        
  456.                                                         facebook.request( "me/feed", "POST", {
  457.                                                                 message=statusUpdate,
  458.                                                                 name="Download Ghosts vs. Monsters to Compete with Me!",
  459.                                                                 caption="Ghosts vs. Monsters - Sample app created with the Corona SDK by Ansca Mobile.",
  460.                                                                 link="http://itunes.apple.com/us/app/your-app-name/id382456881?mt=8",
  461.                                                                 picture="http://www.yoursite.com/link-to-90x90-image.png" } )
  462.                                                 end
  463.                                         end
  464.                                 end
  465.                                
  466.                                 facebook.login( fbAppID, facebookListener, { "publish_stream" } )
  467.                                 ]]--
  468.                         end
  469.                 end
  470.                
  471.                 fbBtn = ui.newButton{
  472.                         defaultSrc = "facebookbtn.png",
  473.                         defaultX = 302,
  474.                         defaultY = 40,
  475.                         overSrc = "facebookbtn-over.png",
  476.                         overX = 302,
  477.                         overY = 40,
  478.                         onEvent = onFBTouch,
  479.                         id = "FacebookButton",
  480.                         text = "",
  481.                         font = "Helvetica",
  482.                         textColor = { 255, 255, 255, 255 },
  483.                         size = 16,
  484.                         emboss = false
  485.                 }
  486.                
  487.                 fbBtn.x = 240; fbBtn.y = 220
  488.                 fbBtn.alpha = 0
  489.                
  490.                 if isWin == "yes" then
  491.                         fbBtn.isVisible = true
  492.                         fbBtn.isActive = true
  493.                 else
  494.                         fbBtn.isVisible = false
  495.                         fbBtn.isActive = false
  496.                 end
  497.                
  498.                 -- INSERT ALL ITEMS INTO GROUP
  499.                 hudGroup:insert( shadeRect )
  500.                 hudGroup:insert( ofBtn )
  501.                 hudGroup:insert( fbBtn )
  502.                 hudGroup:insert( gameOverDisplay )
  503.                 hudGroup:insert( menuBtn )
  504.                 hudGroup:insert( restartBtn )
  505.                 if isWin == "yes" then hudGroup:insert( nextBtn ); end
  506.                
  507.                 -- FADE IN ALL GAME OVER ELEMENTS
  508.                 transition.to( shadeRect, { time=200, alpha=0.65 } )
  509.                 transition.to( gameOverDisplay, { time=500, alpha=1 } )
  510.                 transition.to( menuBtn, { time=500, alpha=1 } )
  511.                 transition.to( restartBtn, { time=500, alpha=1 } )
  512.                 if isWin == "yes" then transition.to( nextBtn, { time=500, alpha=1 } ); end
  513.                 transition.to( ofBtn, { time=500, alpha=1, y=68, transition=easing.inOutExpo } )
  514.                 if isWin == "yes" then transition.to( fbBtn, { time=500, alpha=1, y=255, transition=easing.inOutExpo } ); end
  515.                
  516.                 -- MAKE SURE SCORE TEXT IS VISIBLE (if player won the round)
  517.                 if isWin == "yes" then
  518.                         scoreText.isVisible = false
  519.                         local oldScoreText = scoreText.text
  520.                         scoreText.text = "Score: " .. oldScoreText
  521.                         scoreText.xScale = 0.5; scoreText.yScale = 0.5  --> for clear retina display text
  522.                         scoreText.x = (480 - (scoreText.contentWidth * 0.5)) - 30
  523.                         scoreText.y = 30
  524.                         scoreText:toFront()
  525.                         timer.performWithDelay( 1000, function() scoreText.isVisible = true; end, 1 )
  526.                 else
  527.                         --scoreText:removeSelf()
  528.                         display.remove( scoreText )
  529.                         scoreText = nil
  530.                 end
  531.                
  532.                 -- Update Best Score
  533.                 if gameScore > bestScore then
  534.                         bestScore = gameScore
  535.                         local bestScoreFilename = restartModule .. ".data"
  536.                         saveValue( bestScoreFilename, tostring(bestScore) )
  537.                 end
  538.                
  539.                 -- MAKE SURE BEST SCORE TEXT IS VISIBLE
  540.                 bestScoreText = display.newText( "0", 10, 300, "Helvetica-Bold", 32 )
  541.                 bestScoreText:setTextColor( 228, 228, 228, 255 )        --> white
  542.                 bestScoreText.text = "Best Score For This Level: " .. comma_value( bestScore )
  543.                 bestScoreText.xScale = 0.5; bestScoreText.yScale = 0.5  --> for clear retina display text
  544.                 bestScoreText.x = (bestScoreText.contentWidth * 0.5) + 15
  545.                 bestScoreText.y = 304
  546.                
  547.                 hudGroup:insert( bestScoreText )
  548.         end
  549.        
  550.         local callNewRound = function( shouldPoof, instantPoof )
  551.                 local shouldPoof = shouldPoof
  552.                 local instantPoof = instantPoof
  553.                 local isGameOver = false
  554.                
  555.                 if blastGlow.isVisible then
  556.                         blastGlow.isVisible = false
  557.                 end
  558.                
  559.                 if gameLives >= 1 then
  560.                         gameLives = gameLives - 1
  561.                        
  562.                         if gameLives == 3 then
  563.                                 life4.alpha = 0.3
  564.                                 if monsterCount < 1 then isGameOver = true; end
  565.                         elseif gameLives == 2 then
  566.                                 life4.alpha = 0.3
  567.                                 life3.alpha = 0.3
  568.                                 if monsterCount < 1 then isGameOver = true; end
  569.                         elseif gameLives == 1 then
  570.                                 life4.alpha = 0.3
  571.                                 life3.alpha = 0.3
  572.                                 life2.alpha = 0.3
  573.                                 if monsterCount < 1 then isGameOver = true; end
  574.                         elseif gameLives == 0 then
  575.                                 life4.alpha = 0.3
  576.                                 life3.alpha = 0.3
  577.                                 life2.alpha = 0.3
  578.                                 life1.alpha = 0.3
  579.                                 isGameOver = true
  580.                         end
  581.                 elseif gameLives < 0 then
  582.                         gameLives = 0
  583.                         life4.alpha = 0.3
  584.                         life3.alpha = 0.3
  585.                         life2.alpha = 0.3
  586.                         life1.alpha = 0.3
  587.                         isGameOver = true
  588.                 else
  589.                         life4.alpha = 0.3
  590.                         life3.alpha = 0.3
  591.                         life2.alpha = 0.3
  592.                         life1.alpha = 0.3
  593.                         isGameOver = true
  594.                 end
  595.                        
  596.                
  597.                 if shouldPoof then
  598.                                
  599.                         local poofTheGhost = function()
  600.                                 local theDelay = 300
  601.                                
  602.                                 -- Make ghost disappear and show "poof" animation
  603.                                 ghostObject:setLinearVelocity( 0, 0 )
  604.                                 ghostObject.bodyType = "static"
  605.                                 ghostObject.isVisible = false
  606.                                 ghostObject.isBodyActive = false
  607.                                 ghostObject.rotation = 0
  608.                                
  609.                                 -- Poof code below --
  610.                                 audio.play( ghostPoofSound )
  611.                                 poofObject.x = ghostObject.x; poofObject.y = ghostObject.y
  612.                                 poofObject.alpha = 0
  613.                                 poofObject.isVisible = true
  614.                                
  615.                                 local fadePoof = function()
  616.                                         transition.to( poofObject, { time=2000, alpha=0 } )    
  617.                                 end
  618.                                 transition.to( poofObject, { time=100, alpha=1.0, onComplete=fadePoof } )
  619.                                
  620.                                 -- Move camera to far right to see effect
  621.                                 if gameGroup.x > -480 then
  622.                                         local camTween = transition.to( gameGroup, { time=500, x=-480 } )
  623.                                 end
  624.                                
  625.                                 local continueBlink = function()
  626.                                          local startBlinking = function()
  627.                                                 if continueText.isVisible then
  628.                                                         continueText.isVisible = false
  629.                                                 else
  630.                                                         continueText.isVisible = true
  631.                                                 end
  632.                                          end
  633.                                          
  634.                                          continueTimer = timer.performWithDelay( 350, startBlinking, 0 )
  635.                                 end
  636.                                
  637.                                 restartTimer = timer.performWithDelay( theDelay, function()
  638.                                         waitingForNewRound = true;
  639.                                         continueBlink();
  640.                                 end, 1 )
  641.                                
  642.                                 --[[
  643.                                 if not isGameOver then
  644.                                         restartTimer = timer.performWithDelay( theDelay, function() waitingForNewRound = true; end, 1 )
  645.                                 else
  646.                                         if monsterCount > 0 then
  647.                                                 restartTimer = timer.performWithDelay( theDelay, function() callGameOver( "no" ); end, 1 )
  648.                                         else
  649.                                                 restartTimer = timer.performWithDelay( 3000, function() callGameOver( "yes" ); end, 1 )
  650.                                         end
  651.                                 end
  652.                                 ]]--
  653.                         end
  654.                        
  655.                         if instantPoof == "yes" then
  656.                                 local poofTimer = timer.performWithDelay( 500, poofTheGhost, 1 )
  657.                         else
  658.                                 local poofTimer = timer.performWithDelay( 1700, poofTheGhost, 1 )
  659.                         end
  660.                 else
  661.                        
  662.                         ghostObject:setLinearVelocity( 0, 0 )
  663.                         ghostObject.bodyType = "static"
  664.                         ghostObject.isVisible = false
  665.                         ghostObject.isBodyActive = false
  666.                         ghostObject.rotation = 0
  667.                        
  668.                         --restartTimer = timer.performWithDelay( 300, startNewRound, 1 )
  669.                        
  670.                         if not isGameOver then
  671.                                 restartTimer = timer.performWithDelay( 300, startNewRound, 1 )
  672.                         else
  673.                                 if monsterCount > 0 then
  674.                                         restartTimer = timer.performWithDelay( 300, function() callGameOver( "no" ); end, 1 )
  675.                                 else
  676.                                         restartTimer = timer.performWithDelay( 300, function() callGameOver( "yes" ); end, 1 )
  677.                                 end
  678.                         end
  679.                 end
  680.         end
  681.        
  682.         local drawBackground = function()
  683.                 -- Background gets drawn in this order: backdrop, clouds, trees, red glow
  684.                
  685.                 -- BACKDROP
  686.                 backgroundImage1 = display.newImageRect( backgroundFilename1, 480, 320 )
  687.                 backgroundImage1:setReferencePoint( display.CenterLeftReferencePoint )
  688.                 backgroundImage1.x = 0; backgroundImage1.y = 160
  689.                
  690.                 backgroundImage2 = display.newImageRect( backgroundFilename2, 480, 320 )
  691.                 backgroundImage2:setReferencePoint( display.CenterLeftReferencePoint )
  692.                 backgroundImage2.x = 480; backgroundImage2.y = 160
  693.                
  694.                 gameGroup:insert( backgroundImage1 )
  695.                 gameGroup:insert( backgroundImage2 )
  696.                
  697.                 -- CLOUDS
  698.                 clouds1 = display.newImageRect( "clouds-left.png", 480, 320 )
  699.                 clouds1.x = 240; clouds1.y = 160
  700.                
  701.                 clouds2 = display.newImageRect( "clouds-right.png", 480, 320 )
  702.                 clouds2.x = 720; clouds2.y = 160
  703.                
  704.                 clouds3 = display.newImageRect( "clouds-left.png", 480, 320 )
  705.                 clouds3.x = 1200; clouds3.y = 160
  706.                
  707.                 clouds4 = display.newImageRect( "clouds-right.png", 480, 320 )
  708.                 clouds4.x = 1680; clouds4.y = 160
  709.                
  710.                 gameGroup:insert( clouds1 )
  711.                 gameGroup:insert( clouds2 )
  712.                 gameGroup:insert( clouds3 )
  713.                 gameGroup:insert( clouds4 )
  714.                
  715.                 -- TREES
  716.                 local treesLeft = display.newImageRect( "trees-left.png", 480, 320 )
  717.                 treesLeft.x = 240; treesLeft.y = 160
  718.                
  719.                 local treesRight = display.newImageRect( "trees-right.png", 480, 320 )
  720.                 treesRight.x = 720; treesRight.y = 160
  721.                
  722.                 gameGroup:insert( treesLeft )
  723.                 gameGroup:insert( treesRight )
  724.                
  725.                 -- RED GLOW
  726.                 --[[
  727.                 local redGlow = display.newImageRect( "redglow.png", 480, 320 )
  728.                 redGlow.x = 725; redGlow.y = 160
  729.                 redGlow.alpha = 0.5
  730.                
  731.                 gameGroup:insert( redGlow )
  732.                 ]]--
  733.         end
  734.        
  735.         local drawHUD = function()
  736.                 -- TWO BLACK RECTANGLES AT TOP AND BOTTOM (for those viewing from iPad)
  737.                 local topRect = display.newRect( 0, -160, 480, 160 )
  738.                 topRect:setFillColor( 0, 0, 0, 255 )
  739.                
  740.                 local bottomRect = display.newRect( 0, 320, 480, 160 )
  741.                 bottomRect:setFillColor( 0, 0, 0, 255 )
  742.                
  743.                 hudGroup:insert( topRect )
  744.                 hudGroup: insert( bottomRect )
  745.                
  746.                 -- LIVES DISPLAY
  747.                 life1 = display.newImageRect( "lifeicon.png", 22, 22 )
  748.                 life1.x = 20; life1.y = 18
  749.                
  750.                 life2 = display.newImageRect( "lifeicon.png", 22, 22 )
  751.                 life2.x = life1.x + 25; life2.y = 18
  752.                
  753.                 life3 = display.newImageRect( "lifeicon.png", 22, 22 )
  754.                 life3.x = life2.x + 25; life3.y = 18
  755.                
  756.                 life4 = display.newImageRect( "lifeicon.png", 22, 22 )
  757.                 life4.x = life3.x + 25; life4.y = 18
  758.                
  759.                 hudGroup:insert( life1 )
  760.                 hudGroup:insert( life2 )
  761.                 hudGroup:insert( life3 )
  762.                 hudGroup:insert( life4 )
  763.                
  764.                 -- SCORE DISPLAY
  765.                 scoreText = display.newText( "0", 470, 22, "Helvetica-Bold", 52 )
  766.                 scoreText:setTextColor( 255, 255, 255, 255 )    --> white
  767.                 scoreText.text = gameScore
  768.                 scoreText.xScale = 0.5; scoreText.yScale = 0.5  --> for clear retina display text
  769.                 scoreText.x = (480 - (scoreText.contentWidth * 0.5)) - 15
  770.                 scoreText.y = 20
  771.                
  772.                 hudGroup:insert( scoreText )
  773.                
  774.                 -- TAP TO CONTINUE DISPLAY
  775.                 continueText = display.newText( "TAP TO CONTINUE", 240, 18, "Helvetica", 36 )
  776.                 continueText:setTextColor( 249, 203, 64, 255 )
  777.                 continueText.xScale = 0.5; continueText.yScale = 0.5
  778.                 continueText.x = 240; continueText.y = 18
  779.                 continueText.isVisible = false
  780.                
  781.                 hudGroup:insert( continueText )
  782.                
  783.                 -- PAUSE BUTTON
  784.                 local onPauseTouch = function( event )
  785.                         if event.phase == "release" and pauseBtn.isActive then
  786.                                 audio.play( tapSound )
  787.                                
  788.                                 -- Pause the game
  789.                                
  790.                                 if gameIsActive then
  791.                                
  792.                                         gameIsActive = false
  793.                                         physics.pause()
  794.                                        
  795.                                         -- SHADE
  796.                                         if not shadeRect then
  797.                                                 shadeRect = display.newRect( 0, 0, 480, 320 )
  798.                                                 shadeRect:setFillColor( 0, 0, 0, 255 )
  799.                                                 hudGroup:insert( shadeRect )
  800.                                         end
  801.                                         shadeRect.alpha = 0.5
  802.                                        
  803.                                         -- SHOW MENU BUTTON
  804.                                         if pauseMenuBtn then
  805.                                                 pauseMenuBtn.isVisible = true
  806.                                                 pauseMenuBtn.isActive = true
  807.                                                 pauseMenuBtn:toFront()
  808.                                         end
  809.                                        
  810.                                         pauseBtn:toFront()
  811.                                        
  812.                                         -- STOP GHOST ANIMATION
  813.                                         if ghostTween then
  814.                                                 transition.cancel( ghostTween )
  815.                                         end
  816.                                 else
  817.                                        
  818.                                         if shadeRect then
  819.                                                 --shadeRect:removeSelf()
  820.                                                 display.remove( shadeRect )
  821.                                                 shadeRect = nil
  822.                                         end
  823.                                        
  824.                                         if pauseMenuBtn then
  825.                                                 pauseMenuBtn.isVisible = false
  826.                                                 pauseMenuBtn.isActive = false
  827.                                         end
  828.                                        
  829.                                         gameIsActive = true
  830.                                         physics.start()
  831.                                        
  832.                                         -- START Ghost animation back up
  833.                                         if ghostTween then
  834.                                                 transition.cancel( ghostTween )
  835.                                         end
  836.                                        
  837.                                         local function ghostAnimation()
  838.                                                 local animUp = function()
  839.                                                         if ghostObject.inAir or shotOrb.isVisible then
  840.                                                                 transition.cancel( ghostTween )
  841.                                                         else
  842.                                                                 ghostTween = transition.to( ghostObject, { time=375, y=190, onComplete=ghostAnimation })
  843.                                                         end
  844.                                                 end
  845.                                                
  846.                                                 if ghostObject.inAir or shotOrb.isVisible then
  847.                                                         transition.cancel( ghostTween )
  848.                                                 else
  849.                                                         ghostTween = transition.to( ghostObject, { time=375, y=200, onComplete=animUp })
  850.                                                 end
  851.                                         end
  852.                                        
  853.                                         ghostTween = transition.to( ghostObject, { time=375, y=190, onComplete=ghostAnimation })
  854.                                 end
  855.                         end
  856.                 end
  857.                
  858.                 pauseBtn = ui.newButton{
  859.                         defaultSrc = "pausebtn.png",
  860.                         defaultX = 44,
  861.                         defaultY = 44,
  862.                         overSrc = "pausebtn-over.png",
  863.                         overX = 44,
  864.                         overY = 44,
  865.                         onEvent = onPauseTouch,
  866.                         id = "PauseButton",
  867.                         text = "",
  868.                         font = "Helvetica",
  869.                         textColor = { 255, 255, 255, 255 },
  870.                         size = 16,
  871.                         emboss = false
  872.                 }
  873.                
  874.                 pauseBtn.x = 442; pauseBtn.y = 288
  875.                 pauseBtn.isVisible = false
  876.                 pauseBtn.isActive = false
  877.                
  878.                 hudGroup:insert( pauseBtn )
  879.                
  880.                 -- MENU BUTTON (on Pause Display)
  881.                 local onMenuPauseTouch = function( event )
  882.                         if event.phase == "release" and pauseMenuBtn.isActive then
  883.                                
  884.                                 audio.play( tapSound )
  885.                                
  886.                                 local onComplete = function ( event )
  887.                                         if "clicked" == event.action then
  888.                                                 local i = event.index
  889.                                                 if i == 2 then
  890.                                                         -- Player click 'Cancel'; do nothing, just exit the dialog
  891.                                                 elseif i == 1 then
  892.                                                         -- Player clicked Yes, go to main menu
  893.                                                         director:changeScene( "loadmainmenu" )
  894.                                                 end
  895.                                         end
  896.                                 end
  897.                                
  898.                                 -- Show alert with two buttons
  899.                                 local alert = native.showAlert( "Are You Sure?", "Your current game will end.",
  900.                                                                                                                 { "Yes", "Cancel" }, onComplete )
  901.                         end
  902.                 end
  903.                
  904.                 pauseMenuBtn = ui.newButton{
  905.                         defaultSrc = "pausemenubtn.png",
  906.                         defaultX = 44,
  907.                         defaultY = 44,
  908.                         overSrc = "pausemenubtn-over.png",
  909.                         overX = 44,
  910.                         overY = 44,
  911.                         onEvent = onMenuPauseTouch,
  912.                         id = "PauseMenuButton",
  913.                         text = "",
  914.                         font = "Helvetica",
  915.                         textColor = { 255, 255, 255, 255 },
  916.                         size = 16,
  917.                         emboss = false
  918.                 }
  919.                
  920.                 pauseMenuBtn.x = 38; pauseMenuBtn.y = 288
  921.                 pauseMenuBtn.isVisible = false
  922.                 pauseMenuBtn.isActive = false
  923.                
  924.                 hudGroup:insert( pauseMenuBtn )
  925.         end
  926.        
  927.         local createGround = function()
  928.                 groundLight1 = display.newImageRect( "groundlight.png", 228, 156 )
  929.                 groundLight1.x = 150; groundLight1.y = 190
  930.                
  931.                 groundObject1 = display.newImageRect( "ground1.png", 480, 76 )
  932.                 groundObject1:setReferencePoint( display.BottomLeftReferencePoint )
  933.                 groundObject1.x = 0; groundObject1.y = 320
  934.                
  935.                 groundObject2 = display.newImageRect( "ground2.png", 480, 76 )
  936.                 groundObject2:setReferencePoint( display.BottomLeftReferencePoint )
  937.                 groundObject2.x = 480; groundObject2.y = 320
  938.                
  939.                 groundObject1.myName = "ground"
  940.                 groundObject2.myName = "ground"
  941.                
  942.                 local groundShape = { -240,-18, 240,-18, 240,18, -240,18 }
  943.                 physics.addBody( groundObject1, "static", { density=1.0, bounce=0, friction=0.5, shape=groundShape } )
  944.                 physics.addBody( groundObject2, "static", { density=1.0, bounce=0, friction=0.5, shape=groundShape } )
  945.                
  946.                 gameGroup:insert( groundLight1 )
  947.                 gameGroup:insert( groundObject1 )
  948.                 gameGroup:insert( groundObject2 )
  949.         end
  950.        
  951.         local createShotOrb = function()
  952.                 shotOrb = display.newImageRect( "orb.png", 96, 96 )
  953.                 shotOrb.xScale = 1.0; shotOrb.yScale = 1.0
  954.                 shotOrb.isVisible = false
  955.                
  956.                 gameGroup:insert( shotOrb )
  957.         end
  958.        
  959.         local createGhost = function()
  960.                
  961.                 local onGhostCollision = function( self, event )
  962.                         if event.phase == "began" then
  963.                                
  964.                                 audio.play( impactSound )
  965.                                
  966.                                 if ghostObject.isHit == false then
  967.                                
  968.                                         if blastGlow.isVisible then
  969.                                                 blastGlow.isVisible = false
  970.                                         end
  971.                                        
  972.                                        
  973.                                         if dotTimer then timer.cancel( dotTimer ); end
  974.                                         ghostObject.isHit = true
  975.                                        
  976.                                         if event.other.myName == "wood" or event.other.myName == "stone" or event.other.myName == "tomb" or event.other.myName == "monster" then
  977.                                                 callNewRound( true, "yes" )
  978.                                         else
  979.                                                 callNewRound( true, "no" )
  980.                                         end
  981.                                        
  982.                                         local newScore = gameScore + 500
  983.                                         setScore( newScore )
  984.                                
  985.                                 elseif ghostObject.isHit then
  986.                                         return true
  987.                                 end
  988.                         end
  989.                 end
  990.                
  991.                 -- first, create the transparent arrow that shows up
  992.                 shotArrow = display.newImageRect( "arrow.png", 240, 240 )
  993.                 shotArrow.x = 150; shotArrow.y = 195
  994.                 shotArrow.isVisible = false
  995.                
  996.                 gameGroup:insert( shotArrow )
  997.                
  998.                 ghostObject = movieclip.newAnim({ "ghost1-waiting.png", "ghost1.png" }, 26, 26 )
  999.                 ghostObject.x = 150; ghostObject.y = 195
  1000.                 ghostObject.isVisible = false
  1001.                
  1002.                 ghostObject.isReady = false     --> Not "flingable" until touched.
  1003.                 ghostObject.inAir = false
  1004.                 ghostObject.isHit = false
  1005.                 ghostObject.isBullet = true
  1006.                 ghostObject.trailNum = 0
  1007.                
  1008.                 ghostObject.radius = 12
  1009.                 physics.addBody( ghostObject, "static", { density=1.0, bounce=0.4, friction=0.15, radius=ghostObject.radius } )
  1010.                 ghostObject.rotation = 0
  1011.                 ghostObject:stopAtFrame( 1 )
  1012.                
  1013.                 -- START up and down animation
  1014.                
  1015.                 --ghostTween = transition.to( ghostObject, { time=200, y=192, onComplete=ghostAnimation })
  1016.                
  1017.                 -- END up and down animation
  1018.                
  1019.                 -- Set up collisions
  1020.                 ghostObject.collision = onGhostCollision
  1021.                 ghostObject:addEventListener( "collision", ghostObject )
  1022.                
  1023.                 -- Create the Blast Glow
  1024.                 blastGlow = display.newImageRect( "blastglow.png", 54, 54 )
  1025.                 blastGlow.x = ghostObject.x; blastGlow.y = ghostObject.y
  1026.                 blastGlow.isVisible = false
  1027.                
  1028.                 -- Create Poof Objects
  1029.                 poofObject = display.newImageRect( "poof.png", 80, 70 )
  1030.                 poofObject.alpha = 1.0
  1031.                 poofObject.isVisible = false
  1032.                
  1033.                 greenPoof = display.newImageRect( "greenpoof.png", 80, 70 )
  1034.                 greenPoof.alpha = 1.0
  1035.                 greenPoof.isVisible = false
  1036.                
  1037.                 -- Insert objects into main group
  1038.                 gameGroup:insert( trailGroup )
  1039.                 gameGroup:insert( blastGlow )
  1040.                 gameGroup:insert( ghostObject )
  1041.                 gameGroup:insert( poofObject )
  1042.                 gameGroup:insert( greenPoof )
  1043.         end
  1044.        
  1045.         local onMonsterPostCollision = function( self, event )
  1046.                 if event.force > 1.5 and self.isHit == false then
  1047.                         audio.play( monsterPoofSound )
  1048.                        
  1049.                         self.isHit = true
  1050.                         print( "Monster destroyed! Force: " .. event.force )
  1051.                         self.isVisible = false
  1052.                         self.isBodyActive = false
  1053.                        
  1054.                         -- Poof code below --
  1055.                         if poofTween then transition.cancel( poofTween ); end
  1056.                        
  1057.                         greenPoof.x = self.x; greenPoof.y = self.y
  1058.                         greenPoof.alpha = 0
  1059.                         greenPoof.isVisible = true
  1060.                        
  1061.                         local fadePoof = function()
  1062.                                 transition.to( greenPoof, { time=500, alpha=0 } )      
  1063.                         end
  1064.                         poofTween = transition.to( greenPoof, { time=50, alpha=1.0, onComplete=fadePoof } )
  1065.                        
  1066.                         monsterCount = monsterCount - 1
  1067.                         if monsterCount < 0 then monsterCount = 0; end
  1068.                        
  1069.                         self.parent:remove( self )
  1070.                         self = nil
  1071.                        
  1072.                         local newScore = gameScore + mCeil(5000 * event.force)
  1073.                         setScore( newScore )
  1074.                 end
  1075.         end
  1076.        
  1077.         local onScreenTouch = function( event )
  1078.                 if gameIsActive then
  1079.                         if event.phase == "began" and ghostObject.inAir == false and event.xStart > 115 and event.xStart < 180 and event.yStart > 160 and event.yStart < 230 and screenPosition == "left" then
  1080.                                
  1081.                                 transition.cancel( ghostTween )
  1082.                                 ghostObject.y = 195
  1083.                                 ghostObject.isReady = true
  1084.                                 shotOrb.isVisible = true
  1085.                                 shotOrb.alpha = 0.75
  1086.                                 shotOrb.x = ghostObject.x; shotOrb.y = ghostObject.y
  1087.                                 shotOrb.xScale = 0.1; shotOrb.yScale = 0.1
  1088.                                
  1089.                                 shotArrow.isVisible = true
  1090.                        
  1091.                         elseif event.phase == "began" and waitingForNewRound then
  1092.                                
  1093.                                 waitingForNewRound = false
  1094.                                 if continueTimer then timer.cancel( continueTimer ); end
  1095.                                 continueText.isVisible = false
  1096.                                
  1097.                                 if gameLives < 1 then
  1098.                                         -- GAME OVER
  1099.                                         if monsterCount < 1 then
  1100.                                                 callGameOver( "yes" )
  1101.                                         else
  1102.                                                 callGameOver( "no" )
  1103.                                         end
  1104.                                 elseif monsterCount < 1 and gameLives >= 1 then
  1105.                                        
  1106.                                         callGameOver( "yes" )
  1107.                                 else
  1108.                                         startNewRound()
  1109.                                 end
  1110.                        
  1111.                         elseif event.phase == "began" and waitingForNewRound == false then
  1112.                                
  1113.                                 if continueTimer then timer.cancel( continueTimer ); end
  1114.                                 continueText.isVisible = false
  1115.                                
  1116.                                 if gameLives < 1 then
  1117.                                         -- GAME OVER
  1118.                                         if monsterCount < 1 then
  1119.                                                 callGameOver( "yes" )
  1120.                                         else
  1121.                                                 callGameOver( "no" )
  1122.                                         end
  1123.                                 elseif monsterCount < 1 and gameLives >= 1 then
  1124.                                        
  1125.                                         callGameOver( "yes" )
  1126.                                 end
  1127.                                
  1128.                         elseif event.phase == "ended" and ghostObject.isReady == false and ghostObject.inAir == false and canSwipe == true then
  1129.                                
  1130.                                 local leftRight
  1131.                                
  1132.                                 if event.xStart > event.x then
  1133.                                         leftRight = "left"
  1134.                                 elseif event.xStart < event.x then
  1135.                                         leftRight = "right"
  1136.                                 end
  1137.                                
  1138.                                 -- Swipe to view other end of the screen
  1139.                                 if leftRight == "left" and screenPosition == "left" and event.xStart > 180 then
  1140.                                         -- Swiped game screen to the left
  1141.                                         print( "Swiped left!" )
  1142.                                         canSwipe = false
  1143.                                        
  1144.                                         local switchPosition = function()
  1145.                                                 screenPosition = "right"
  1146.                                                 local swipeTimer = timer.performWithDelay( 200, function() canSwipe = true; end, 1 )
  1147.                                         end
  1148.                                        
  1149.                                         if swipeTween then
  1150.                                                 transition.cancel( swipeTween )
  1151.                                         end
  1152.                                        
  1153.                                         if (event.xStart - event.x) >= 100 then
  1154.                                                 swipeTween = transition.to( gameGroup, { time=700, x=-480, onComplete=switchPosition } )
  1155.                                         else
  1156.                                                 swipeTween = transition.to( gameGroup, { time=100, x=0, onComplete=function() canSwipe = true; end } )
  1157.                                         end
  1158.                                        
  1159.                                 elseif leftRight == "right" and screenPosition == "right" then
  1160.                                         -- Swiped screen to the right
  1161.                                         print( "Swiped right!" )
  1162.                                         canSwipe = false
  1163.                                        
  1164.                                         local switchPosition = function()
  1165.                                                 screenPosition = "left"
  1166.                                                 local swipeTimer = timer.performWithDelay( 200, function() canSwipe = true; end, 1 )
  1167.                                         end
  1168.                                        
  1169.                                         if swipeTween then
  1170.                                                 transition.cancel( swipeTween )
  1171.                                         end
  1172.                                        
  1173.                                         if (event.x - event.xStart) >= 100 then
  1174.                                                 swipeTween = transition.to( gameGroup, { time=700, x=0, onComplete=switchPosition } )
  1175.                                         else
  1176.                                                 swipeTween = transition.to( gameGroup, { time=100, x=-480, onComplete=function() canSwipe = true; end } )
  1177.                                         end
  1178.                                        
  1179.                                 end
  1180.                                
  1181.                         elseif event.phase == "ended" and ghostObject.isReady then
  1182.                                 -- Finger lifted from screen; fling the Roly Poly!
  1183.                                
  1184.                                 local flingNow = function()
  1185.                                         -- handle the shot orb and disable screen swiping
  1186.                                         transition.cancel( ghostTween )
  1187.                                         shotOrb.isVisible = false
  1188.                                         shotArrow.isVisible = false
  1189.                                         canSwipe = false
  1190.                                        
  1191.                                         local x = event.x
  1192.                                         local y = event.y
  1193.                                         local xForce = (-1 * (x - ghostObject.x)) * 2.15        --> 2.75
  1194.                                         local yForce = (-1 * (y - ghostObject.y)) * 2.15        --> 2.75
  1195.                                        
  1196.                                         audio.play( weeSound )
  1197.                                        
  1198.                                         ghostObject:stopAtFrame( 2 )
  1199.                                         ghostObject.bodyType = "dynamic"
  1200.                                         ghostObject:applyForce( xForce, yForce, ghostObject.x, ghostObject.y )
  1201.                                         ghostObject.isReady = false
  1202.                                         ghostObject.inAir = true
  1203.                                        
  1204.                                         -- START TRAILING DOTS BLOCK
  1205.                                         local i
  1206.                                        
  1207.                                         -- First, delete previous trail
  1208.                                         for i = trailGroup.numChildren,1,-1 do
  1209.                                                 local child = trailGroup[i]
  1210.                                                 child.parent:remove( child )
  1211.                                                 child = nil
  1212.                                         end
  1213.                                        
  1214.                                         local startDotCreation = function()
  1215.                                                 local createDot = function()
  1216.                                                         local trailDot
  1217.                                                        
  1218.                                                         if ghostObject.trailNum == 0 then
  1219.                                                                 trailDot = display.newCircle( gameGroup, ghostObject.x, ghostObject.y, 2.5 )
  1220.                                                         else
  1221.                                                                 trailDot = display.newCircle( gameGroup, ghostObject.x, ghostObject.y, 1.5 )
  1222.                                                         end
  1223.                                                         trailDot:setFillColor( 255, 255, 255, 255 )
  1224.                                                         trailDot.alpha = 1.0
  1225.                                                        
  1226.                                                         trailGroup:insert( trailDot )
  1227.                                                         --gameGroup:insert( trailGroup )
  1228.                                                        
  1229.                                                        
  1230.                                                         if ghostObject.trailNum == 0 then
  1231.                                                                 ghostObject.trailNum = 1
  1232.                                                         else
  1233.                                                                 ghostObject.trailNum = 0
  1234.                                                         end
  1235.                                                 end
  1236.                                                
  1237.                                                 dotTimer = timer.performWithDelay( 50, createDot, 50 )
  1238.                                         end
  1239.                                        
  1240.                                         local startDotTimer = timer.performWithDelay( 50, startDotCreation, 1 )
  1241.                                         -- END TRAILING DOTS BLOCK
  1242.                                        
  1243.                                         -- Show the blast glow
  1244.                                         blastGlow.x = ghostObject.x
  1245.                                         blastGlow.y = ghostObject.y
  1246.                                         blastGlow.isVisible = true
  1247.                                 end
  1248.                                
  1249.                                 transition.to( shotOrb, { time=175, xScale=0.1, yScale=0.1, onComplete=flingNow } )
  1250.                                
  1251.                                 audio.play( blastOffSound )
  1252.                                
  1253.                                 -- Make sure pause button is hidden/inactive
  1254.                                 pauseBtn.isVisible = false
  1255.                                 pauseBtn.isActive = false
  1256.                         end
  1257.                        
  1258.                         if shotOrb.isVisible == true then
  1259.                                
  1260.                                 local xOffset = ghostObject.x
  1261.                                 local yOffset = ghostObject.y
  1262.                                
  1263.                                 -- Formula math.sqrt( ((event.y - yOffset) ^ 2) + ((event.x - xOffset) ^ 2) )
  1264.                                 local distanceBetween = mCeil(mSqrt( ((event.y - yOffset) ^ 2) + ((event.x - xOffset) ^ 2) ))
  1265.                                
  1266.                                 shotOrb.xScale = -distanceBetween * 0.02
  1267.                                 shotOrb.yScale = -distanceBetween * 0.02
  1268.                                
  1269.                                 -- Formula: 90 + (math.atan2(y2 - y1, x2 - x1) * 180 / PI)
  1270.                                 local angleBetween = mCeil(mAtan2( (event.y - yOffset), (event.x - xOffset) ) * 180 / mPi) + 90
  1271.                                
  1272.                                 ghostObject.rotation = angleBetween + 180
  1273.                                 shotArrow.rotation = ghostObject.rotation
  1274.                         end
  1275.                        
  1276.                         if canSwipe == true then
  1277.                                
  1278.                                 if screenPosition == "left" then
  1279.                                         -- Swipe left to go right
  1280.                                         if event.xStart > 180 then
  1281.                                                 gameGroup.x = event.x - event.xStart
  1282.                                                
  1283.                                                 if gameGroup.x > 0 then
  1284.                                                         gameGroup.x = 0
  1285.                                                         canSwipe = true
  1286.                                                 end
  1287.                                         end
  1288.                                                
  1289.                                 elseif screenPosition == "right" then
  1290.                                         -- Swipe right to go to the left
  1291.                                         gameGroup.x = (event.x - event.xStart) - 480
  1292.                                        
  1293.                                         if gameGroup.x < -480 then
  1294.                                                 gameGroup.x = -480
  1295.                                                 canSwipe = true
  1296.                                         end
  1297.                                 end
  1298.                         end
  1299.                 end
  1300.         end
  1301.        
  1302.         -- Main enterFrame Listener
  1303.         local gameLoop = function()
  1304.                 if gameIsActive then
  1305.                         -- CAMERA CONTROL
  1306.                         if ghostObject.x > 240 and ghostObject.x < 720 and not waitingForNewRound then
  1307.                                 gameGroup.x = -ghostObject.x + 240
  1308.                         end
  1309.                                
  1310.                        
  1311.                         -- MAKE SURE GHOST's Rotation Doesn't Go Past Limits
  1312.                         if ghostObject.inAir then
  1313.                                 if ghostObject.rotation < -45 then
  1314.                                         ghostObject.rotation = -45
  1315.                                 elseif ghostObject.rotation > 30 then
  1316.                                         ghostObject.rotation = 30
  1317.                                 end
  1318.                         end
  1319.                        
  1320.                         -- Make sure Blast Glow's Rotation is Equal to the Ghost's
  1321.                         if blastGlow.isVisible then
  1322.                                 blastGlow.rotation = ghostObject.rotation
  1323.                                 blastGlow.x = ghostObject.x - 10
  1324.                                 blastGlow.y = ghostObject.y + 3
  1325.                         end
  1326.                        
  1327.                        
  1328.                         -- MOVE CLOUDS SLOWLY
  1329.                         local cloudMoveSpeed = 0.5
  1330.                        
  1331.                         clouds1.x = clouds1.x - cloudMoveSpeed
  1332.                         clouds2.x = clouds2.x - cloudMoveSpeed
  1333.                         clouds3.x = clouds3.x - cloudMoveSpeed
  1334.                         clouds4.x = clouds4.x - cloudMoveSpeed
  1335.                        
  1336.                         if clouds1.x <= -240 then
  1337.                                 clouds1.x = 1680
  1338.                         end
  1339.                        
  1340.                         if clouds2.x <= -240 then
  1341.                                 clouds2.x = 1680
  1342.                         end
  1343.                        
  1344.                         if clouds3.x <= -240 then
  1345.                                 clouds3.x = 1680
  1346.                         end
  1347.                        
  1348.                         if clouds4.x <= -240 then
  1349.                                 clouds4.x = 1680
  1350.                         end
  1351.                         -- END CLOUD MOVEMENT
  1352.                        
  1353.                         -- CHECK IF GHOST GOES PAST SCREEN
  1354.                         if ghostObject.isHit == false and ghostObject.x >= 960 then
  1355.                                 ghostObject.isHit = true
  1356.                                 if dotTimer then timer.cancel( dotTimer ); end
  1357.                                 callNewRound( false, "no" )
  1358.                         end
  1359.                        
  1360.                         if ghostObject.isHit == false and ghostObject.x < 0 then
  1361.                                 if dotTimer then timer.cancel( dotTimer ); end
  1362.                                 ghostObject.isHit = true
  1363.                                 if dotTimer then timer.cancel( dotTimer ); end
  1364.                                 callNewRound( false, "no" )
  1365.                         end
  1366.                 end
  1367.         end
  1368.        
  1369.         local reorderLayers = function()
  1370.                
  1371.                 gameGroup:insert( levelGroup )
  1372.                 groundObject1:toFront()
  1373.                 groundObject2:toFront()
  1374.                 ghostObject:toFront()
  1375.                 poofObject:toFront()
  1376.                 greenPoof:toFront()
  1377.                 hudGroup:toFront()
  1378.                
  1379.         end
  1380.        
  1381.         -- *********************************************************************************************
  1382.        
  1383.         -- createLevel() function (should be the only function that's different in each level module
  1384.        
  1385.         -- *********************************************************************************************
  1386.        
  1387.         local createLevel = function()
  1388.                
  1389.                 restartModule = "level1"
  1390.                 nextModule = "level2"
  1391.                 monsterCount = 2
  1392.        
  1393.                 -- FIRST VERTICAL SLAB
  1394.                 local vSlab1 = display.newImageRect( "vertical-stone.png", 28, 58 )
  1395.                 vSlab1.x = 600; vSlab1.y = 215
  1396.                 vSlab1.myName = "stone"
  1397.                
  1398.                 physics.addBody( vSlab1, "dynamic", { density=stoneDensity, bounce=0, friction=0.5, shape=vSlabShape } )
  1399.                 levelGroup:insert( vSlab1 )
  1400.                
  1401.                 -- SECOND VERTICAL SLAB
  1402.                 local vSlab2 = display.newImageRect( "vertical-stone.png", 28, 58 )
  1403.                 vSlab2.x = 646; vSlab2.y = 215
  1404.                 vSlab2.myName = "stone"
  1405.                
  1406.                 physics.addBody( vSlab2, "dynamic", { density=stoneDensity, bounce=0, friction=0.5, shape=vSlabShape } )
  1407.                 levelGroup:insert( vSlab2 )
  1408.                
  1409.                 -- FIRST VERTICAL PLANK
  1410.                 local vPlank1 = display.newImageRect( "vertical-wood.png", 14, 98 )
  1411.                 vPlank1.x = 623; vPlank1.y = 215
  1412.                 vPlank1.myName = "wood"
  1413.                
  1414.                 physics.addBody( vPlank1, "dynamic", { density=woodDensity, bounce=0, friction=0.5, shape=vPlankShape } )
  1415.                 levelGroup:insert( vPlank1 )
  1416.                
  1417.                 -- SECOND VERTICAL PLANK
  1418.                 local vPlank2 = display.newImageRect( "vertical-wood.png", 14, 98 )
  1419.                 vPlank2.x = 723; vPlank2.y = 215
  1420.                 vPlank2.myName = "wood"
  1421.                
  1422.                 physics.addBody( vPlank2, "dynamic", { density=woodDensity, bounce=0, friction=0.5, shape=vPlankShape } )
  1423.                 levelGroup:insert( vPlank2 )
  1424.                
  1425.                 -- THIRD VERTICAL PLANK
  1426.                 local vPlank3 = display.newImageRect( "vertical-wood.png", 14, 98 )
  1427.                 vPlank3.x = 821; vPlank3.y = 215
  1428.                 vPlank3.myName = "wood"
  1429.                
  1430.                 physics.addBody( vPlank3, "dynamic", { density=woodDensity, bounce=0, friction=0.5, shape=vPlankShape } )
  1431.                 levelGroup:insert( vPlank3 )
  1432.                
  1433.                 -- SECOND VERTICAL SLAB STACK
  1434.                 local vSlab3 = display.newImageRect( "vertical-stone.png", 28, 58 )
  1435.                 vSlab3.x = 800; vSlab3.y = 215
  1436.                 vSlab3.myName = "stone"
  1437.                
  1438.                 physics.addBody( vSlab3, "dynamic", { density=stoneDensity, bounce=0, friction=0.5, shape=vSlabShape } )
  1439.                 levelGroup:insert( vSlab3 )
  1440.                
  1441.                 local vSlab4 = display.newImageRect( "vertical-stone.png", 28, 58 )
  1442.                 vSlab4.x = 843; vSlab4.y = 215
  1443.                 vSlab4.myName = "stone"
  1444.                
  1445.                 physics.addBody( vSlab4, "dynamic", { density=stoneDensity, bounce=0, friction=0.5, shape=vSlabShape } )
  1446.                 levelGroup:insert( vSlab4 )
  1447.                
  1448.                 -- HORIZONTAL PLANK 1
  1449.                 local hPlank1 = display.newImageRect( "horizontal-wood.png", 98, 14 )
  1450.                 hPlank1.x = 674; hPlank1.y = 162
  1451.                 hPlank1.myName = "wood"
  1452.                
  1453.                 physics.addBody( hPlank1, "dynamic", { density=woodDensity, bounce=0, friction=0.5, shape=hPlankShape } )
  1454.                 levelGroup:insert( hPlank1 )
  1455.                
  1456.                 -- HORIZONTAL PLANK 2
  1457.                 local hPlank2 = display.newImageRect( "horizontal-wood.png", 98, 14 )
  1458.                 hPlank2.x = 772; hPlank2.y = 162
  1459.                 hPlank2.myName = "wood"
  1460.                
  1461.                 physics.addBody( hPlank2, "dynamic", { density=woodDensity, bounce=0, friction=0.5, shape=hPlankShape } )
  1462.                 levelGroup:insert( hPlank2 )
  1463.                
  1464.                 local hPlank4 = display.newImageRect( "horizontal-wood.png", 98, 14 )
  1465.                 hPlank4.x = 723; hPlank4.y = 143
  1466.                 hPlank4.myName = "wood"
  1467.                
  1468.                 physics.addBody( hPlank4, "dynamic", { density=woodDensity, bounce=0, friction=0.5, shape=hPlankShape } )
  1469.                 levelGroup:insert( hPlank4 )
  1470.                
  1471.                 -- TOP TOMBSTONES
  1472.                 local tombStone1 = display.newImageRect( "tombstone.png", 38, 46 )
  1473.                 tombStone1.x = 650; tombStone1.y = 128
  1474.                 tombStone1.myName = "tomb"
  1475.                
  1476.                 physics.addBody( tombStone1, "dynamic", { density=woodDensity, bounce=0, friction=0.5, shape=tombShape } )
  1477.                 levelGroup:insert( tombStone1 )
  1478.                
  1479.                 local tombStone2 = display.newImageRect( "tombstone.png", 38, 46 )
  1480.                 tombStone2.x = 796; tombStone2.y = 128
  1481.                 tombStone2.myName = "tomb"
  1482.                
  1483.                 physics.addBody( tombStone2, "dynamic", { density=woodDensity, bounce=0, friction=0.5, shape=tombShape } )
  1484.                 levelGroup:insert( tombStone2 )
  1485.                
  1486.                 -- MONSTERS
  1487.                 local monster1 = display.newImageRect( "monster.png", 26, 30 )
  1488.                 monster1.x = 745; monster1.y = 125
  1489.                 monster1.myName = "monster"
  1490.                 monster1.isHit = false
  1491.                
  1492.                 physics.addBody( monster1, "dynamic", { density=monsterDensity, bounce=0, friction=0.5, shape=monsterShape } )
  1493.                 levelGroup:insert( monster1 )
  1494.                
  1495.                 monster1.postCollision = onMonsterPostCollision
  1496.                 monster1:addEventListener( "postCollision", monster1 )
  1497.                
  1498.                 local monster2 = display.newImageRect( "monster.png", 26, 30 )
  1499.                 monster2.x = 700; monster2.y = 125
  1500.                 monster2.myName = "monster"
  1501.                 monster2.isHit = false
  1502.                
  1503.                 monster2.postCollision = onMonsterPostCollision
  1504.                 monster2:addEventListener( "postCollision", monster2 )
  1505.                
  1506.                 physics.addBody( monster2, "dynamic", { density=monsterDensity, bounce=0, friction=0.5, shape=monsterShape } )
  1507.                 levelGroup:insert( monster2 )
  1508.                
  1509.                 -- SET PROPER DRAW ORDER:
  1510.                 reorderLayers()
  1511.         end
  1512.        
  1513.         -- *********************************************************************************************
  1514.        
  1515.         -- END createLevel() function
  1516.        
  1517.         -- *********************************************************************************************
  1518.        
  1519.         local onSystem = function( event )
  1520.                 if event.type == "applicationSuspend" then
  1521.                         if gameIsActive and pauseBtn.isVisible then
  1522.                                 gameIsActive = false
  1523.                                 physics.pause()
  1524.                                
  1525.                                 -- SHADE
  1526.                                 if not shadeRect then
  1527.                                         shadeRect = display.newRect( 0, 0, 480, 320 )
  1528.                                         shadeRect:setFillColor( 0, 0, 0, 255 )
  1529.                                         hudGroup:insert( shadeRect )
  1530.                                 end
  1531.                                 shadeRect.alpha = 0.5
  1532.                                
  1533.                                 -- SHOW MENU BUTTON
  1534.                                 if pauseMenuBtn then
  1535.                                         pauseMenuBtn.isVisible = true
  1536.                                         pauseMenuBtn.isActive = true
  1537.                                         pauseMenuBtn:toFront()
  1538.                                 end
  1539.                                
  1540.                                 pauseBtn:toFront()
  1541.                                
  1542.                                 -- STOP GHOST ANIMATION
  1543.                                 if ghostTween then
  1544.                                         transition.cancel( ghostTween )
  1545.                                 end
  1546.                         end
  1547.                        
  1548.                 elseif event.type == "applicationExit" then
  1549.                         if system.getInfo( "environment" ) == "device" then
  1550.                                 -- prevents iOS 4+ multi-tasking crashes
  1551.                                 os.exit()
  1552.                         end
  1553.                 end
  1554.         end
  1555.        
  1556.         local gameInit = function()
  1557.                
  1558.                 -- PHYSICS
  1559.                 physics.start( true )
  1560.                 physics.setDrawMode( "normal" ) -- set to "debug" or "hybrid" to see collision boundaries
  1561.                 physics.setGravity( 0, 11 )     --> 0, 9.8 = Earth-like gravity
  1562.                
  1563.                 -- DRAW GAME OBJECTS
  1564.                 drawBackground()
  1565.                 createGround()
  1566.                 createShotOrb()
  1567.                 createGhost()
  1568.                
  1569.                 -- CREATE LEVEL
  1570.                 createLevel()
  1571.                
  1572.                 -- DRAW HEADS-UP DISPLAY (score, lives, etc)
  1573.                 drawHUD()
  1574.                
  1575.                 -- LOAD BEST SCORE FOR THIS LEVEL
  1576.                 local bestScoreFilename = restartModule .. ".data"
  1577.                 local loadedBestScore = loadValue( bestScoreFilename )  --> restartModule should be "level1" or "level2", etc.
  1578.                
  1579.                 bestScore = tonumber(loadedBestScore)
  1580.                
  1581.                 -- START EVENT LISTENERS
  1582.                 Runtime:addEventListener( "touch", onScreenTouch )
  1583.                 Runtime:addEventListener( "enterFrame", gameLoop )
  1584.                 Runtime:addEventListener( "system", onSystem )
  1585.                
  1586.                 local startTimer = timer.performWithDelay( 2000, function() startNewRound(); end, 1 )
  1587.         end
  1588.        
  1589.         --[[
  1590.         local monitorMem = function()
  1591.                 collectgarbage()
  1592.                 print( "\nMemUsage: " .. collectgarbage("count") )
  1593.          
  1594.                 local textMem = system.getInfo( "textureMemoryUsed" ) / 1000000
  1595.                 print( "TexMem:   " .. textMem )
  1596.         end
  1597.        
  1598.         Runtime:addEventListener( "enterFrame", monitorMem )
  1599.         ]]--
  1600.        
  1601.         local cleanSounds = function()
  1602.                
  1603.                 audio.stop()
  1604.                
  1605.                 if tapSound then
  1606.                         audio.dispose( tapSound )
  1607.                         tapSound = nil
  1608.                 end
  1609.                
  1610.                 if blastOffSound then
  1611.                         audio.dispose( blastOffSound )
  1612.                         blastOffSound = nil
  1613.                 end
  1614.                
  1615.                 if ghostPoofSound then
  1616.                         audio.dispose( ghostPoofSound )
  1617.                         ghostPoofSound = nil
  1618.                 end
  1619.                
  1620.                 if monsterPoofSound then
  1621.                         audio.dispose( monsterPoofSound )
  1622.                         monsterPoofSound = nil
  1623.                 end
  1624.                
  1625.                 if impactSound then
  1626.                         audio.dispose( impactSound )
  1627.                         impactSound = nil
  1628.                 end
  1629.                
  1630.                 if weeSound then
  1631.                         audio.dispose( weeSound )
  1632.                         weeSound = nil
  1633.                 end
  1634.                
  1635.                 if newRoundSound then
  1636.                         audio.dispose( newRoundSound )
  1637.                         newRoundSound = nil
  1638.                 end
  1639.                
  1640.                 if youWinSound then
  1641.                         audio.dispose( youWinSound )
  1642.                         youWinSound = nil
  1643.                 end
  1644.                
  1645.                 if youLoseSound then
  1646.                         audio.dispose( youLoseSound )
  1647.                         youLoseSound = nil
  1648.                 end
  1649.         end
  1650.        
  1651.         clean = function()
  1652.                
  1653.                 --Runtime:removeEventListener( "enterFrame", monitorMem )
  1654.                
  1655.                 -- STOP PHYSICS ENGINE
  1656.                 physics.stop()
  1657.                
  1658.                 -- REMOVE EVENT LISTENERS
  1659.                 Runtime:removeEventListener( "touch", onScreenTouch )
  1660.                 Runtime:removeEventListener( "enterFrame", gameLoop )
  1661.                 Runtime:removeEventListener( "system", onSystem )
  1662.                
  1663.                 -- REMOVE everything in other groups
  1664.                 for i = hudGroup.numChildren,1,-1 do
  1665.                         local child = hudGroup[i]
  1666.                         child.parent:remove( child )
  1667.                         child = nil
  1668.                 end
  1669.                
  1670.                 --hudGroup:removeSelf()
  1671.                 display.remove( hudGroup )
  1672.                 hudGroup = nil
  1673.                
  1674.                 if trailGroup then
  1675.                         --trailGroup:removeSelf()
  1676.                         display.remove( trailGroup )
  1677.                         trailGroup = nil
  1678.                 end
  1679.                
  1680.                 if levelGroup then
  1681.                         --levelGroup:removeSelf()
  1682.                         display.remove( levelGroup )
  1683.                         levelGroup = nil
  1684.                 end
  1685.                
  1686.                 -- Stop any transitions
  1687.                 if ghostTween then transition.cancel( ghostTween ); end
  1688.                 if poofTween then transition.cancel( poofTween ); end
  1689.                 if swipeTween then transition.cancel( swipeTween ); end
  1690.                
  1691.                 -- Stop any timers
  1692.                 if restartTimer then timer.cancel( restartTimer ); end
  1693.                 if continueTimer then timer.cancel( continueTimer ); end
  1694.                
  1695.                 -- unload audio files from memory
  1696.                 cleanSounds()
  1697.         end
  1698.        
  1699.         gameInit()
  1700.        
  1701.         -- MUST return a display.newGroup()
  1702.         return gameGroup
  1703. end