-- -- Abstract: ShapeTumbler sample project -- Demonstrates polygon body constructor and tilt-based gravity effects (on device only) -- -- Version: 1.1 (revised for Alpha 2) -- -- Sample code is MIT licensed, see http://developer.anscamobile.com/code/license -- Copyright (C) 2010 ANSCA Inc. All Rights Reserved. --[[ objGroup is the display group go() starts the app by calling gotoLevel(1) gotoLevel() clears things, resets physics, and adds new things. ]]-- local physics = require("physics") -- local levelLoader = require("loadLevel") local maxBullets=2 local lastSentBullet=0 local bullets = {} --local lastDropX = {} --local lastDropY= {} local bkg=nil local lastBulletIndex = 0 -- the last started index, useful when choosing -- LRU to reuse -- contants local launcherOffset=10 local rainOffset=0 local bulletSpeed=400 local NUM_BKG_CYCLES=3 -- vars local lastLiveTimeCheck=0 local totalScore=0 local score=0 local scoreB=0 local blocks={} local drops={} local reddrops={} local timeBeforeRain=15 local rainWarningTime=2 local timeBeforeRainWarning=timeBeforeRain-rainWarningTime local redSource=nil local bkgIndex=1 local bkgs={"lava1_magenta.jpg", "lava1_yellow.jpg", "lava1_cyan.jpg", "lava1_orange.jpg", "lava1_green.jpg", "lava1_white.jpg", "lava1.jpg"} local currentBkgCycle=1 -- where the last block was dropped, used to test for distance local mouseDownX=0 local mouseDownY=0 local launcherObj=nil -- POINTS local PT_DROPBLOCK=1 local PT_FLOWERGROW=5 local PT_BLACKFLOWERGROW=-5 local PT_LIVEFLOWER=1 local PT_LIVEBLACKFLOWER=-1 display.setStatusBar( display.HiddenStatusBar ) local blockImgs={"1.png", "2.png", "3.png", "4.png", "5.png", "6.png", "7.png"} local flowerImgs={"flwr1.png", "flwr2.png", "flwr3.png", "flwr4.png", "flwr5.png", "flwr6.png", "flwr7.png"} local blackFlowerImgs={"flwr_blk1.png", "flwr_blk2.png"} local flowers = {} local blackflowers = {} -- local lastBlockImgIndex = 1 local function setupPhysics() physics.start() --physics.setDrawMode("debug") --physics.setDrawMode("hybrid") physics.setDrawMode("normal") physics.setScale( 60 ) --physics.setGravity( 0, 9.8 ) -- initial gravity points downwards physics.setGravity( 0, 0 ) -- initial gravity points downwards system.setAccelerometerInterval( 100 ) -- set accelerometer to maximum responsiveness end -- tilt affects gravity function onTilt( event ) physics.setGravity( ( 9.8 * event.yGravity ), ( -9.8 * event.xGravity ) ) end function EnableGravity() physics.setGravity( 0, 9.8 ) -- initial gravity points downwards Runtime:addEventListener( "accelerometer", onTilt ) end function DisableGravity() physics.setGravity( 0, 0 ) Runtime:removeEventListener( "accelerometer", onTilt ) end local level = 1 function moveGrav( event) local phase = event.phase if ("ended" == phase) or ("moved" == phase) then x = (event.x - display.contentWidth / 2) / (display.contentWidth / 2) y = (event.y - display.contentHeight / 2) / (display.contentHeight / 2) physics.setGravity( ( 9.8 * x), ( 9.8 * y) ) end end TP_NONE=0 TP_LAUNCH=10 TP_BLOCK=11 TP_WATERSPHERE=12 TP_FLOWER=13 TP_BULLET=14 TP_REDSOURCE=15 TP_REDSPHERE=16 TP_BLACKFLOWER=17 objGroup = display.newGroup() local function addPhysicsObj(triObj) if nil == triObj then return end --print ("Adding A:", triObjs[i].typ, triObjs[i].img) shape = nil radius = nil collType="dynamic" --if triObjs[i].img == "triangle.png" then --[[ if triObj.typ == TP_TRI then shape = triangleShape dens = 0.9 frict = 0.5 bounce = 0.3 --physics.addBody( triObjs[i], { density=0.9, friction=0.5, bounce=0.3, shape=triangleShape } ) --elseif triObjs[i].img == "pentagon.png" then elseif triObj.typ == TP_PENT then shape = pentagonShape dens = 0.9 frict = 0.5 bounce = 0.4 --physics.addBody( triObjs[i], { density=0.9, friction=0.5, bounce=0.4, shape=pentagonShape } ) --elseif triObjs[i].img == "super_ball.png" then elseif triObj.typ == TP_SUPERBALL then dens=0.9 frict=0.5 bounce = 0.8 radius = 24 elseif triObj.typ == TP_SOCCERBALL then --elseif triObjs[i].img == "soccer_ball.png" then dens=0.9 frict=0.5 bounce = 0.6 radius = 38 elseif triObj.typ == TP_CRATEA then dens=2 frict=0.5 bounce = 0.4 elseif triObj.typ == TP_CRATEB then dens=4 frict=0.5 bounce = 0.4 elseif triObj.typ == TP_CRATEC then dens=1 frict=0.5 bounce = 0.4 ]]-- if triObj.typ == TP_BLOCK then dens=1 frict=0.5 bounce = 0.4 collType="static" elseif triObj.typ == TP_LAUNCH then dens=1 frict=0.5 bounce = 0.4 collType="static" elseif triObj.typ == TP_FLOWER or triObj.typ == TP_BLACKFLOWER then dens=0.01 frict=0.1 bounce = 0.4 collType="dynamic" -- since it can be scaled, get the shape right shape={-triObj.width/2*triObj.scaleFactor, -triObj.height/2*triObj.scaleFactor, triObj.width/2*triObj.scaleFactor, triObj.height/2*triObj.scaleFactor} elseif triObj.typ == TP_BULLET then dens=5.0 frict=0.5 bounce = 0.05 collType="dynamic" radius=28 elseif triObj.typ == TP_REDSOURCE then dens=5.0 frict=0.5 bounce = 0.5 collType="static" radius=18 elseif triObj.typ == TP_WATERSPHERE then dens=0.9 frict=0.5 bounce = 0.5 local tmp = math.random() local tmpScale=tmp*.6+.2 triObj:scale(tmpScale, tmpScale) triObj.scaleFactor=tmpScale radius = 35 * tmpScale elseif triObj.typ == TP_REDSPHERE then dens=0.9 frict=0.5 bounce = 0.5 local tmp = math.random() local tmpScale=tmp*.6+.2 triObj:scale(tmpScale, tmpScale) triObj.scaleFactor=tmpScale radius = 35 * tmpScale elseif triObj.typ == nil then print ("ERROR: typ is nil in creation: ", triObj.img) else print ("ERROR: typ not handled in creation: ", triObj.typ) end if nil ~= shape then -- explicit shapes, triangle, pentagon physics.addBody( triObj, collType, { density=dens, friction=frict, bounce=bounce, shape=shape } ) elseif nil ~= radius then -- circle physics.addBody( triObj, collType, { density=dens, friction=frict, bounce=bounce, radius=radius } ) else -- box physics.addBody( triObj, collType, { density=dens, friction=frict, bounce=bounce, } ) end --print ("Adding:", triObjs[i].typ) -- objTypes[triObjs[i].typ] = 1 end local function addPhysicsObjs(triObjs) for i = 1, #triObjs do addPhysicsObj(triObjs[i]) end end local function checkIfFinished(groupOfObjs) -- if there are two of any type, we're not finished -- just local tmpObjTypes = {} --for (k,v) in pairs(groupOfObjs) do for i = 1, groupOfObjs.numChildren do -- obj type = groupOfObjs[i].typ if tmpObjTypes[groupOfObjs[i].typ] ~= nil then -- this means a repeat type return false end tmpObjTypes[groupOfObjs[i].typ] = 1 end return true --print ("test for end:", numTypes, objGroup.numChildren, numTypes == objGroup.numChildren) --print (numTypes == objGroup.numChildren) --if (#objTypes == objGroup.numChildren) then --print ("returning true") --return true --end ----else --return false ----end end local endLevelAnimationStarted = false local function animateEndOfLevel() endLevelAnimationStarted = true bkg:removeSelf() end -- METHOD 2: Use a runtime listener to globally report collisions between "object1" and "object2" -- Note that the order of object1 and object2 may be reported arbitrarily in any collision --[[ local function onGlobalCollision( event ) if ( event.phase == "began" ) then if event.object1.typ == event.object2.typ then if event.object1.typ ~= TP_BORDER then --event.object1:removeSelf() removeAndBlinkObj(event.object1) end if event.object2.typ ~= TP_BORDER then --event.object2:removeSelf() removeAndBlinkObj(event.object2) end --if checkIfFinished(objGroup) then --if false == endLevelAnimationStarted then --animateEndOfLevel() --timer.performWithDelay( 1000, gotoNextLevel() ) --end --end end --print( "Global report: " .. event.object1.myName .. " & " .. event.object2.myName .. " collision began" ) elseif ( event.phase == "ended" ) then --print( "Global report: " .. event.object1.myName .. " & " .. event.object2.myName .. " collision ended" ) end --print( "**** " .. event.element1 .. " -- " .. event.element2 ) --print(objGroup.numChildren) end Runtime:addEventListener( "collision", onGlobalCollision ) ]]-- local checkIfFinishedDelay = 1 -- 500 local function checkIfFinishedLoop() if checkIfFinished(objGroup) then if false == endLevelAnimationStarted then if level <= numLevels then -- don't end the final screen animateEndOfLevel() print "adding timer to gotonext" timer.performWithDelay( 1500, gotoNextLevel ) end end else -- not finished yet timer.performWithDelay( checkIfFinishedDelay, checkIfFinishedLoop ) end end function highscoresetup() score = 0 local fontSize=18 totalScoreText = display.newText('Total Score:', 5, 2, native.systemFont, 18) totalScoreText:setTextColor(255, 255, 50) --scoreNum = display.newText('0', 54, 2, 'akashi', 14) --see addPoints() for placement totalScoreNum = display.newText('0', 2, 2, native.systemFont, 18) totalScoreNum:setTextColor(255,255,50) totalScoreNum:setReferencePoint(display.CenterLeftReferencePoint) totalScoreNum.x = totalScoreText.x+52 -- level = 1 --scoreText = display.newText('Score:', 5, 2, 'akashi', 14) scoreText = display.newText('Score(+):', 5, display.contentHeight-fontSize-2, native.systemFont, 18) scoreText:setTextColor(255, 122, 50) --scoreNum = display.newText('0', 54, 2, 'akashi', 14) --see addPoints() for placement scoreNum = display.newText('0', 2, display.contentHeight-fontSize-2, native.systemFont, 18) scoreNum:setTextColor(255,122,50) scoreNum:setReferencePoint(display.CenterLeftReferencePoint) scoreNum.x = scoreText.x+42 -- scoreTextB = display.newText('Score(-):', display.contentWidth-100, display.contentHeight-fontSize-2, native.systemFont, 18) scoreTextB:setTextColor(200, 127, 127) scoreTextB:rotate(math.pi) scoreNumB = display.newText('0', display.contentWidth-fontSize-64, display.contentHeight-fontSize-2, native.systemFont, 18) scoreNumB:setReferencePoint(display.CenterLeftReferencePoint) scoreNumB.x = scoreTextB.x+38 scoreNumB:setTextColor(200,127,127) scoreNumB:rotate(math.pi) end function _addPointsTotal(amount) totalScore = totalScore + amount totalScoreNum.text = totalScore -- * SCORE_CONST totalScoreNum:setReferencePoint(display.CenterLeftReferencePoint) totalScoreNum.x = totalScoreText.x+52 end function addPoints(amount) score = score + amount scoreNum.text = score -- * SCORE_CONST scoreNum:setReferencePoint(display.CenterLeftReferencePoint) scoreNum.x = scoreText.x + 42 -- 86 _addPointsTotal(amount) end function addPointsRed(amount) scoreB = scoreB + amount scoreNumB.text = scoreB -- * SCORE_CONST scoreNumB:setReferencePoint(display.CenterLeftReferencePoint) scoreNumB.x = scoreTextB.x+38 _addPointsTotal(amount) end function TextToFront() totalScoreText:toFront() totalScoreNum:toFront() scoreText:toFront() scoreNum:toFront() scoreTextB:toFront() scoreNumB:toFront() end local function go() gotoLevel(1) highscoresetup() --bkg:addEventListener("touch", moveGrav) end local function clear() for i = objGroup.numChildren, 1, -1 do -- iterate backward -- modifying list will iterating objGroup[i]:removeSelf() end print ("remaining chilcren, should be 0: ", objGroup.numChildren) -- already done in removeBorders() --for i = #borders, 1, -1 do -- iterate backward -- modifying list will iterating -- borders[i]:removeSelf() --end stopCustomUpdate() end local function ClearBlocks() for i = #blocks, 1, -1 do -- iterate backward -- modifying list will iterating local child = blocks[i] if (nil ~= child) then child:removeSelf() end end blocks = nil blocks = {} end local function ClearDrops() for i = #drops, 1, -1 do -- iterate backward -- modifying list will iterating local child = drops[i] if (nil ~= child) then child:removeSelf() end end drops = nil drops = {} end local function ClearRedDrops() for i = #reddrops, 1, -1 do -- iterate backward -- modifying list will iterating local child = reddrops[i] if (nil ~= child) then child:removeSelf() end end reddrops = nil reddrops = {} end --[[ --list test a = {} a[1] = 1 a[2] = 2 a[3] = 3 a[1] = nil print ("len a: ", #a) for i = 1, #a do print (a[i]) end for i = 1, #a do print (a[i]) end ]]-- local function sendCannonBall(x,y) -- determine which bullet obj to use (max of 3 bullets or so) local index = 1 if #bullets < maxBullets then bullets[#bullets+1] = display.newImage( "cannonball.png") index = #bullets lastbulletIndex = index else lastBulletIndex = lastBulletIndex + 1 if lastBulletIndex > maxBullets then lastBulletIndex = 1 end --to reuse physics obj, need to remove it, otherwise speed etc is kept index = lastBulletIndex if bullets[index] ~= nil then bullets[index]:removeSelf() bullets[index] = nil end end -- print (x, y) local bullet = bullets[index] -- recreate bullet if obj finished crossing screen and was destroyed if bullet == nil then bullets[index] = display.newImage( "cannonball.png") bullet = bullets[index] end bullet.lastBlockImgIndex=math.random(#blockImgs) bullet.x=x bullet.y=y bullet.lastDropX=x bullet.lastDropY=y bullet.myName='blt' bullet.rotDeg=launcherObj.rotDeg bullet.lastBlock=nil bullet.typ = TP_BULLET addPhysicsObj(bullet) --physics.addBody( bullet, "dynamic", { density=3.0, friction=0.5, bounce=0.05 } ) -- remove the "isBullet" setting below to see the brick pass through cans without colliding! bullet.isBullet = true bullet.angularVelocity = 100 --bullet.angularVelocity = 100 --bullet:applyForce( -200, 0, bullet.x, bullet.y ) --bullet:applyForce( 200* math.cos(launcherObj.rotDeg*math.pi/180), 200*math.sin(launcherObj.rotDeg*math.pi/180), bullet.x, bullet.y ) bullet:applyForce( bulletSpeed* math.cos(launcherObj.rotDeg*math.pi/180), bulletSpeed*math.sin(launcherObj.rotDeg*math.pi/180), bullet.x, bullet.y ) end local function fire( event) -- print ("FIRE, ", event.phase) local phase = event.phase --for k,v in pairs(event) do -- print (k) --end if "began" == phase then --throwBrick(event.x, event.y) -- print (event.target.xOrigin, event.target.x) sendCannonBall(event.target.xOrigin, event.target.yOrigin) --print "threw brick" end end --function addTapToFire(obj) --obj:addEventListener("touch", fire) --end function PositionLauncher(event) local phase = event.phase if "began" == phase then --throwBrick(event.x, event.y) -- print (event.target.xOrigin, event.target.x) --sendCannonBall(event.target.xOrigin, event.target.yOrigin) --print "threw brick" mouseDownX = event.x mouseDownY = event.y --for k,v in pairs(display) do -- print (k) --end xmin = math.min(event.x, display.contentWidth-event.x); ymin = math.min(event.y, display.contentHeight-event.y); if xmin < ymin then if event.x > display.contentWidth/2 then launcherObj.x = display.contentWidth -launcherObj.width / 2 - launcherOffset launcherObj:rotate(180-launcherObj.rotDeg) launcherObj.rotDeg = 180 launcherObj.baseRotDeg = 180 else launcherObj.x = launcherObj.width / 2 + launcherOffset launcherObj:rotate(0-launcherObj.rotDeg) launcherObj.rotDeg = 0 launcherObj.baseRotDeg = 0 end launcherObj.y=event.y else -- xmin >= ymin then if event.y > display.contentHeight/2 then launcherObj.y = display.contentHeight -launcherObj.width / 2 - launcherOffset launcherObj:rotate(270-launcherObj.rotDeg) launcherObj.rotDeg = 270 launcherObj.baseRotDeg = 270 else launcherObj.y = launcherObj.width / 2 + launcherOffset launcherObj:rotate(90-launcherObj.rotDeg) launcherObj.rotDeg = 90 launcherObj.baseRotDeg = 90 end launcherObj.x=event.x end launcherObj:toFront() elseif "moved" == phase then --local xmin = math.min(event.x, display.contentWidth-event.x); -- first clamp --local xtest = math.max(0,event.x) --xtest = math.min(display.contentWidth,event.x) --local ytest = math.max(0,event.y) --ytest = math.min(display.contentHeight,ytest) local tanlen local newRot if xmin < ymin then --tanlen = (event.y-mouseDownY)/(event.x-mouseDownX) --tanlen = (event.y-mouseDownY)/(event.x-launcherObj.x) tanlen = -(event.y-mouseDownY)/(display.contentHeight/20) if mouseDownX > display.contentWidth/2 then tanlen = -tanlen -- right side end newRot = launcherObj.baseRotDeg + math.deg(math.atan( tanlen ) ) else tanlen = -(event.x-mouseDownX)/(display.contentWidth/20) if mouseDownY < display.contentHeight/2 then tanlen = -tanlen -- top end newRot = launcherObj.baseRotDeg + math.deg(math.atan( tanlen ) ) end --local newRot = launcherObj.baseRotDeg + math.deg(math.atan( tanlen ) ) --local newRot = launcherObj.baseRotDeg + math.deg(math.atan( (event.y-launcherObj.x)/(event.x-launcherObj.x) ) ) --local newRot = launcherObj.baseRotDeg + 45 --launcherObj.rotDeg=launcherObj.baseRotDeg -- +launcherObj.offsetRotDeg launcherObj:rotate(-launcherObj.rotDeg) launcherObj:rotate(newRot) launcherObj.rotDeg = newRot elseif "ended" == phase then sendCannonBall(launcherObj.x, launcherObj.y) end end function addTapToPositionLauncher(obj) obj:addEventListener("touch", PositionLauncher) end function removeTapToPositionLauncher(obj) --print ("REMOVE2: ", obj.filename) obj:removeEventListener("touch", PositionLauncher) end function MakeLauncher() launcherObj = display.newImage("launcher.png") launcherObj.x=display.contentWidth launcherObj.y=display.contentHeight/2 launcherObj.typ=TP_LAUNCH launcherObj.baseRotDeg=180 launcherObj.rotDeg=180 launcherObj:rotate(180) return launcherObj end function RemoveLauncher() launcherObj:removeSelf() end function RepositionRedSource() -- don't put too close to the edges redSource.x = (math.random()*.5+.25) *display.contentWidth redSource.y = (math.random()*.5+.25) *display.contentHeight end function AddRedRainSource(img) if nil == img then redSource = display.newImage("blackmarble.png") redSource.isBlack=true else redSource = display.newImage(img) redSource.isBlack=false end RepositionRedSource() redSource.typ = TP_REDSOURCE addPhysicsObj(redSource) return redSource end function ToggleRedSourceColor() local oldX=redSource.x local oldY=redSource.y redSource:removeSelf() if redSource.isBlack then AddRedRainSource("redmarble.png") else AddRedRainSource() end redSource.x=oldX redSource.y=oldY end function ShowWarning(event) InsertSphereDrops() ToggleRedSourceColor() TextToFront() end function NextBkg() bkgIndex = bkgIndex+1 if bkgIndex > #bkgs then bkgIndex=1 end bkg:removeSelf() bkg = display.newImage(bkgs[bkgIndex]) bkg.filename=bkgs[bkgIndex] --"lava1_yellow.png" bkg.x = display.contentWidth/2 bkg.y = display.contentHeight/2 bkg:toBack() end function gotoLevel(levelNum) print ("Goto level ", levelNum) clear() physics.stop() setupPhysics() -- add bkg --bkg = display.newImage("lava1_yellow.jpg") bkg = display.newImage(bkgs[bkgIndex]) bkg.filename=bkgs[bkgIndex] --"lava1_yellow.png" bkg.x = display.contentWidth/2 bkg.y = display.contentHeight/2 AddRedRainSource() -- add launcher MakeLauncher() --addPhysicsObj(launcher) --addTapToFire(launcher) addTapToPositionLauncher(bkg) startCustomUpdate() timer.performWithDelay(timeBeforeRain * 1000, rain) timer.performWithDelay(timeBeforeRainWarning * 1000, ShowWarning) --[[ if areThereAnyBlinkingObjs() then -- don't end while objects are blinking print ("still blinking objs, going to next level") timer.performWithDelay( 1000, gotoNextLevel ) return end --level = level + 1 print ("Goto level ", levelNum) clear() physics.stop() setupPhysics() endLevelAnimationStarted = false local levelDesc = setLevel(levelNum) print ("mainBkg:", levelDesc["mainBkg"]) --bkg = display.newImage( "bkg_wood_symm.png" ) if nil ~= levelDesc["mainBkg"] then bkg = display.newImage( levelDesc["mainBkg"] ) else bkg = display.newImage("bkg_wood_symm.png" ) end bkg.x = display.contentWidth / 2 bkg.y = display.contentHeight / 2 physics.setGravity( 0, 9.8 ) -- initial gravity points downwards -- for debugging in sim, remove before rleas bkg:addEventListener("touch", moveGrav) --print ("BORDER FILES:", levelDesc["borders"]) --print ("First border file:", levelDesc["borders"][0]) setupBorders( levelDesc["borders"] ) local tris = levelDesc["objs"] AssignTypsToObjs(tris) local triObjs = descToObjs(tris) addPhysicsObjs(triObjs) objGroup:toFront() numBlinkingObjs = 0 print "finished resetup" timer.performWithDelay( checkIfFinishedDelay, checkIfFinishedLoop ) ]]-- end function gotoNextLevel(event) level = level + 1 gotoLevel(level) end function ClearDropsIfOffScreen() for i = 1, #drops do local drop = drops[i] if drop ~= nil then break end if (drop.x < -drop.width/2 or drop.x > display.contentWidth+drop.width or drop.y > display.contentHeight+drop.height/2 or drop.y < -drop.height/2) then drop:removeSelf() end end end function ClearFlowersIfOffScreen() --for i = 1, #flowers do for i = #flowers, 1, -1 do -- iterate backward since we're removing some local flower = flowers[i] if flower ~= nil then if (flower.x < -flower.width/2 or flower.x > display.contentWidth+flower.width/2 or flower.y > display.contentHeight+flower.height/2 or flower.y < -flower.height/2) then flower:removeSelf() flowers[i]=nil end end end --print ("f: " , #flowers ) end function ClearBlackFlowersIfOffScreen() --local count=0 --for i = 1, #blackflowers do for i = #blackflowers, 1, -1 do -- iterate backward since we're removing some local flower = blackflowers[i] if flower == nil then break end --count = count +1 if (flower.x < -flower.width/2 or flower.x > display.contentWidth+flower.width/2 or flower.y > display.contentHeight+flower.height/2 or flower.y < -flower.height/2) then flower:removeSelf() blackflowers[i]=nil --print ("Removed bf: " , i ) end end --print ("bf: " , count) end function UpdateLivingPoints() if system.getTimer()-lastLiveTimeCheck < 1000 then return -- only add points every second end lastLiveTimeCheck = system.getTimer() local numLiveFlowers=0 --print ("Iterating thru flowers: ", #flowers) for i = 1, #flowers do if flowers[i] ~= nil then numLiveFlowers = numLiveFlowers+1 --print ("flowers i is counted", i, numLiveFlowers) --else --print ("flowers i is null", i) end end addPoints(numLiveFlowers*PT_LIVEFLOWER) --print ("Added b pts:", numLiveFlowers) local numLiveBlackFlowers=0 for i = 1, #blackflowers do if blackflowers[i] ~= nil then numLiveBlackFlowers = numLiveBlackFlowers+1 end end addPointsRed(numLiveBlackFlowers*PT_LIVEBLACKFLOWER) --print ("Added bf pts:", numLiveBlackFlowers) end function DropBlock(x,y, bullet) --[[ if x > bullet.lastDropX then bullet.lastBlockImgIndex = bullet.lastBlockImgIndex + 1 if bullet.lastBlockImgIndex > #blockImgs then bullet.lastBlockImgIndex = 1 end elseif x < bullet.lastDropX then bullet.lastBlockImgIndex = bullet.lastBlockImgIndex - 1 if bullet.lastBlockImgIndex < 1 then bullet.lastBlockImgIndex = #blockImgs end end ]]-- -- next image index bullet.lastBlockImgIndex = bullet.lastBlockImgIndex + 1 if bullet.lastBlockImgIndex > #blockImgs then bullet.lastBlockImgIndex = 1 end local block = display.newImage(blockImgs[bullet.lastBlockImgIndex]) block.x=x block.y=y block:rotate(bullet.rotDeg) --block:rotate(90) block.typ=TP_BLOCK --addPhysicsObj(block) blocks[#blocks+1] = block addPoints(PT_DROPBLOCK) return block end function customUpdateIteration() --for i = 1, #customUpdateObjs do --customUpdateObjs[i].update() --end for i = 1, #bullets do --if #bullets > 0 then local bullet = bullets[i] if nil == bullet then -- do nothing else -- have bullet obj --for k,v in pairs(bullet) do --print (i, k) --end --print "\n" --if (math.abs(bullet.lastDropX - bullet.x) > 55 or -- math.abs(bullet.lastDropY - bullet.y) > 55) then if (math.sqrt ( (bullet.lastDropX-bullet.x)*(bullet.lastDropX-bullet.x) + (bullet.lastDropY-bullet.y)*(bullet.lastDropY-bullet.y)) > 55) then block = DropBlock(bullet.x, bullet.y, bullet) bullet.lastDropX = bullet.x bullet.lastDropY = bullet.y --if nil ~= bullet.lastBlock then -- if have previous block add physics -- addPhysicsObj(bullet.lastBlock)--now that cannonball is out of the way --end bullet.lastBlock = block bullet:toFront() end -- debug --print ("bullets A:", #bullets) -- remove once off the screen if (bullet.x < -bullet.width/2 or bullet.x > display.contentWidth+bullet.width or bullet.y > display.contentHeight+bullet.height/2 or bullet.y < -bullet.height/2) then local tmpLastBlock = bullet.lastBlock bullet:removeSelf() bullets[i] = nil --if nil ~= tmpLastBlock then -- if have previous block add physics -- addPhysicsObj(tmpLastBlock)--now that cannonball is out of the way --end --print ("bullets B:", #bullets) end end end ClearDropsIfOffScreen() ClearFlowersIfOffScreen() ClearBlackFlowersIfOffScreen() UpdateLivingPoints() end function DropSphere(x,y) local sphere = display.newImage("bluemarble.png") sphere.x=x sphere.y=y --sphere:rotate(bullet.rotDeg) --block:rotate(90) sphere.typ=TP_WATERSPHERE --addPhysicsObj(sphere) drops[#drops+1] = sphere return sphere end function DropRedSphere(x,y) local sphere = display.newImage("redmarble.png") sphere.x=x sphere.y=y --sphere:rotate(bullet.rotDeg) --block:rotate(90) sphere.typ=TP_REDSPHERE addPhysicsObj(sphere) reddrops[#reddrops+1] = sphere return sphere end function RemoveFlowerPhysics() --for i = 1, #flowers do for i = #flowers, 1, -1 do -- iterate backward since we're removing some -- since they're being replaced, shouldn't matter if nil ~= flowers[i] then local oldFlower = flowers[i] local oldImgIndex = oldFlower.imgIndex --print ("TMP INDEX A:", oldImgIndex) local oldX = oldFlower.x local oldY = oldFlower.y local oldScaleFactor = oldFlower.scaleFactor oldFlower:removeSelf() -- recreate it --print ("TMP INDEX:", oldImgIndex) local flower = display.newImage( flowerImgs[oldImgIndex],0, 0 ) flower.x = oldX flower.y = oldY flower.typ = TP_FLOWER flower.scaleFactor = oldScaleFactor flower.imgIndex = oldImgIndex flower:scale(flower.scaleFactor, flower.scaleFactor) flowers[i] = flower end end end function RemoveBlackFlowerPhysics() --for i = 1, #blackflowers do for i = #blackflowers, 1, -1 do -- iterate backward since we're removing some -- since they're being replaced, shouldn't matter if nil ~= blackflowers[i] then local oldFlower = blackflowers[i] local oldImgIndex = oldFlower.imgIndex --print ("TMP INDEX A:", oldImgIndex) local oldX = oldFlower.x local oldY = oldFlower.y local oldScaleFactor = oldFlower.scaleFactor oldFlower:removeSelf() -- recreate it --print ("TMP INDEX:", oldImgIndex) local flower = display.newImage( blackFlowerImgs[oldImgIndex],0, 0 ) flower.x = oldX flower.y = oldY flower.typ = TP_BLACKFLOWER flower.scaleFactor = oldScaleFactor flower.imgIndex = oldImgIndex flower:scale(flower.scaleFactor, flower.scaleFactor) blackflowers[i] = flower end end end function InsertSphereDrops() local x=0 local y=rainOffset local numInX=6 local numInY=4 for i = 1, numInX do --x = (i-1)/(numInX-1) * display.contentWidth x = math.random() * display.contentWidth DropSphere(x,y) end local y=display.contentHeight-rainOffset for i = 1, numInX do --x = (i-1)/(numInX-1) * display.contentWidth x = math.random() * display.contentWidth DropSphere(x,y) end x=rainOffset for i = 2, numInY-1 do --y = (i-1)/(numInY-1) * display.contentHeight y = math.random() * display.contentHeight DropSphere(x,y) end x=display.contentWidth-rainOffset for i = 2, numInY-1 do --y = (i-1)/(numInY-1) * display.contentHeight y = math.random() * display.contentHeight DropSphere(x,y) end end function AddPhysicsToSphereDrops() addPhysicsObjs(drops) end function rain(event) -- remove physics from existing flower blocks (so gravity doesn't make them -- fall away. RemoveLauncher() RemoveFlowerPhysics() RemoveBlackFlowerPhysics() --add physics to all blocks for i = 1, #blocks do addPhysicsObj(blocks[i]) end --print ("REMOVE: ", bkg.filename) removeTapToPositionLauncher(bkg) -- restart gravity EnableGravity() -- blue rain -- start in a box --InsertSphereDrops() AddPhysicsToSphereDrops() -- red rain -- start from redsource for i = 1, 5 do DropRedSphere(redSource.x,redSource.y) end ToggleRedSourceColor() -- back to black timer.performWithDelay(4000, grow) end function grow(event) -- remove blocks ClearBlocks() -- Grow flowers for i = 1, #drops do if drops[i] ~= nil then local imgIndex = math.random(1,#flowerImgs) --print ("flower imgIndex: ", imgIndex) --local flower = display.newImage( flowerImgs[imgIndex],0, 0 ) local flower = display.newImage( flowerImgs[imgIndex],0, 0 ) flower.x = drops[i].x flower.y = drops[i].y flower.typ = TP_FLOWER flower.imgIndex = imgIndex flower.scaleFactor = drops[i].scaleFactor flower:scale(flower.scaleFactor, flower.scaleFactor) flowers[#flowers+1] = flower --print ("Added flower, now total is: ", #flowers) addPoints(PT_FLOWERGROW) end end -- Turn Red water to Black flowers for i = 1, #reddrops do if reddrops[i] ~= nil then local imgIndex = math.random(1,#blackFlowerImgs) --print ("flower imgIndex: ", imgIndex) --local flower = display.newImage( flowerImgs[imgIndex],0, 0 ) local flower = display.newImage( blackFlowerImgs[imgIndex],0, 0 ) flower.x = reddrops[i].x flower.y = reddrops[i].y flower.typ = TP_BLACKFLOWER flower.imgIndex = imgIndex flower.scaleFactor = reddrops[i].scaleFactor flower:scale(flower.scaleFactor, flower.scaleFactor) blackflowers[#blackflowers+1] = flower addPoints(PT_BLACKFLOWERGROW) end end -- clear drops ClearDrops() ClearRedDrops() -- make flowers physical objects --print "Making flowers physics" addPhysicsObjs(flowers) --print "Making bflowers physics" addPhysicsObjs(blackflowers) --print "done Making bflowers physics" -- stop gravity DisableGravity() -- move redSource RepositionRedSource() -- recreate launcher MakeLauncher() -- next bkg, do this before adding touch event to bkg currentBkgCycle = currentBkgCycle+1 if currentBkgCycle > NUM_BKG_CYCLES then NextBkg() currentBkgCycle=1 end -- reenable launcher input addTapToPositionLauncher(bkg) -- prepare rain to restart --timer.performWithDelay(timeBeforeRainWarning * 1000, InsertSphereDropsCallback) timer.performWithDelay(timeBeforeRainWarning * 1000, ShowWarning) timer.performWithDelay(timeBeforeRain * 1000, rain) end function startCustomUpdate() Runtime:addEventListener("enterFrame", customUpdateIteration) end function stopCustomUpdate() Runtime:removeEventListener("enterFrame", customUpdateIteration) end go()