Bug Catcher - A Game Tutorial
Here is a new Tutorial that shows you how to create a simple yet entertaining game for kids, it is called the Bug Catcher, no it does not help you debug your apps...
So what we do is first check if we have had as many flies spawned as we allocated for the level, this is held in the variable counter, which gets incremented everytime we spawn a fly.
if we have spawned as many flies as we need for the level, then we print Game Over to the console, you can add a director scene to either go to the next level or show the game over screen. We just show a message that says Game Over
Then we check if there are as many flies spawned as we allow on the screen, this is handled by the maxFlies variable. We set a variable time between the flies to be spawned using random and countDown to that before we spawn a fly. Then we iterate through every fly on screen and move it based on the speed we assigned to it, some flies will be faster, some will be slower.
There is also an eventHandler that we attach to the frog sprite to handle taps, CatchFly, what we do in this function is call animate the frog flicking his tongue and then check if any fly is in the range of x1 and x2 co-ordinates. This returns the fly that is in that range, so we can then remove or manipulate that fly using the caughtFly function
COMING SOON... once this hits about 500 reads
As one anonymous reader left a note that by the time this post would reach 500 hits the reader would have forgotten about this, it made me wonder and...to make it worth everyones time, including mine. There will be no resources available for this project. The code is up there, the graphics are courtesy of Jake, who has requested that they not be distributed. So you can use whatever graphics you want instead. I can give you the dimensions of the images if that would help.
So while I was fixing the spelling errors (trying to be a spelling Nazi :( ) I understood what Jake was trying to do and he agreed for this to become a tutorial post. So, though the wrong reasons, it worked out quite well.. Thanks again Jake...
The Game
The game is simple, you can tap the big frog in the middle of the pond, he will flick his tongue and catch the fly. You have a certain number of flies that can be spawned and each time you catch a fly successfully, the score increases.The dependencies
SpriteLoq library - The graphics are made by Jake using Flash, so he had SWF files that he has converted using SpriteLoqHow do we do this
The game works on the concept of a central loop, the enterFrame that shall regulate all of the things, We can use timers, but that is not such a clean option in comparison to enterFramefunction onEnterFrame(event) --the heart beat of this app if counter >= tries and fliesOnScreen == 0 then print("Game Over") local text = display.newText("Game Over", 0,0, native.systemFontBold, 256) text:scale(0.5,0.5) text.x = screenW/2 text.y = screenH/2 text.alpha=0 transition.to(text,{time=1000, alpha=1}) Runtime:removeEventListener("enterFrame",onEnterFrame) end if fliesOnScreen < maxFlies then timeBetweenFlies = timeBetweenFlies - 1 if timeBetweenFlies==0 then spawnFly() timeBetweenFlies = random(1,10)+20 end end local k,v for k,v in pairs(flies)do local theFly = v theFly.x = theFly.x + theFly.speed if theFly.x > 1550 then theFly.canMove = false flies[k]=nil removeFly(v) end end end
function spawnFly() if fliesOnScreen >= maxFlies then return end local theFly = _fly.new() if theFly == nil then return end theFly:play("aniFly fly") flies[theFly.ID] = theFly fliesOnScreen = fliesOnScreen + 1 --print("Flies on screen", fliesOnScreen) end
So what we do is first check if we have had as many flies spawned as we allocated for the level, this is held in the variable counter, which gets incremented everytime we spawn a fly.
if we have spawned as many flies as we need for the level, then we print Game Over to the console, you can add a director scene to either go to the next level or show the game over screen. We just show a message that says Game Over
Then we check if there are as many flies spawned as we allow on the screen, this is handled by the maxFlies variable. We set a variable time between the flies to be spawned using random and countDown to that before we spawn a fly. Then we iterate through every fly on screen and move it based on the speed we assigned to it, some flies will be faster, some will be slower.
local function catchFly(event) --Play the frog aniamtion frog:play("aniFrog eat") --Determine if the fly is at the position where the frogs tongue is... --1240 - 1280 is the window that we offer for the frog to catch the fly. local theFly = checkIfAnyFlyIsWithin(1240,1300) if theFly ~= nil then caughtFly(theFly) end end
There is also an eventHandler that we attach to the frog sprite to handle taps, CatchFly, what we do in this function is call animate the frog flicking his tongue and then check if any fly is in the range of x1 and x2 co-ordinates. This returns the fly that is in that range, so we can then remove or manipulate that fly using the caughtFly function
local function checkIfAnyFlyIsWithin(x1, x2) local k,v for k,v in pairs(flies) do if v.x > x1 and v.x < x2 then return v end end end
function caughtFly(thisFly) fliesCaught = fliesCaught + 1 --update the score numberCount.text = string.format("%02d", fliesCaught) --and let us remove this fly removeFly(thisFly) endThe caughtFly function increases the score by 1 and displays it on screen at the foot of the frog and then calls another function to remove that fly, removeFly
function removeFly(thisOne) thisOne:removeSelf() flies[thisOne.ID] = nil thisOne = nil --print("Fly Removed") fliesOnScreen = fliesOnScreen - 1 endThe removeFly function first removes the display item the fly animation, then it removes the item from the array and also updates that fliesOnScreen so we know how many flies are there on the screen.
function _fly.new() if tries < counter then return nil end local flyfactory = loqsprite.newFactory("fly") local aFly = flyfactory:newSpriteGroup() aFly.x = 200; aFly.y = 350 aFly.ID = "Item_" .. counter aFly.speed = random(1,6)+3 aFly.canMove = true counter= counter + 1 return aFly endWhen we spawn a new fly, what we are doing is just creating a new fly and setting the variables to it, this is best handled outside in its own self, it returns nil if we have created as many flies as we allow for the level, otherwise it returns a valid fly.
The full code
display.setStatusBar( display.HiddenStatusBar ) -- HIDE STATUS BAR --Math Functions local random = math.random --requires Loq Sprite local loqsprite = require('loq_sprite') --forward Declaration local caughtFly, removeFly, spawnFly, catchFly local onEnterFrame --Variable we need for the game local i local fliesCaught = 0 local flies = {} local fly local maxFlies = 10 local fliesOnScreen = 0 local _fly={} local counter = 0 local timeBetweenFlies = 1 local tries = 10 local screenW = display.contentWidth local screenH = display.contentHeight --Start creating the Elements on screen --The background local BG = display.newImageRect("background.png", 1024, 768) BG.x = screenW/2; BG.y = screenH/2 --The Frog local ffactory = loqsprite.newFactory("frog") local frog = ffactory:newSpriteGroup() frog.x = 640 ; frog.y = 470 --The Score Text local numberCount = display.newText(string.format("%02d", 0), 0, 0, native.systemFontBold, 40) numberCount.x = frog.x; numberCount.y = frog.y function caughtFly(thisFly) fliesCaught = fliesCaught + 1 --update the score numberCount.text = string.format("%02d", fliesCaught) --and let us remove this fly removeFly(thisFly) end function removeFly(thisOne) thisOne:removeSelf() flies[thisOne.ID] = nil thisOne = nil --print("Fly Removed") fliesOnScreen = fliesOnScreen - 1 end function spawnFly() if fliesOnScreen >= maxFlies then return end local theFly = _fly.new() if theFly == nil then return end theFly:play("aniFly fly") flies[theFly.ID] = theFly fliesOnScreen = fliesOnScreen + 1 --print("Flies on screen", fliesOnScreen) end local function checkIfAnyFlyIsWithin(x1, x2) local k,v for k,v in pairs(flies) do if v.x > x1 and v.x < x2 then return v end end end local function catchFly(event) --Play the frog aniamtion frog:play("aniFrog eat") --Determine if the fly is at the position where the frogs tongue is... --1240 - 1280 is the window that we offer for the frog to catch the fly. local theFly = checkIfAnyFlyIsWithin(1240,1300) if theFly ~= nil then caughtFly(theFly) end end function onEnterFrame(event) --the heart beat of this app if counter >= tries and fliesOnScreen == 0 then print("Game Over") local text = display.newText("Game Over", 0,0, native.systemFontBold, 256) text:scale(0.5,0.5) text.x = screenW/2 text.y = screenH/2 text.alpha=0 transition.to(text,{time=1000, alpha=1}) Runtime:removeEventListener("enterFrame",onEnterFrame) end if fliesOnScreen < maxFlies then timeBetweenFlies = timeBetweenFlies - 1 if timeBetweenFlies==0 then spawnFly() timeBetweenFlies = random(1,10)+20 end end local k,v for k,v in pairs(flies)do local theFly = v theFly.x = theFly.x + theFly.speed if theFly.x > 1550 then theFly.canMove = false flies[k]=nil removeFly(v) end end end Runtime:addEventListener("enterFrame",onEnterFrame) frog:addEventListener("tap", catchFly) function _fly.new() if tries < counter then return nil end local flyfactory = loqsprite.newFactory("fly") local aFly = flyfactory:newSpriteGroup() aFly.x = 200; aFly.y = 350 aFly.ID = "Item_" .. counter aFly.speed = random(1,6)+3 aFly.canMove = true counter= counter + 1 return aFly end
the project in ZIP format
As one anonymous reader left a note that by the time this post would reach 500 hits the reader would have forgotten about this, it made me wonder and...to make it worth everyones time, including mine. There will be no resources available for this project. The code is up there, the graphics are courtesy of Jake, who has requested that they not be distributed. So you can use whatever graphics you want instead. I can give you the dimensions of the images if that would help.
Credits and background
I'd like to thank Jake Scarano for the lovely Artwork and the idea of this game. He has kindly provided the permission to use this for the tutorial. I would also like to tell you of the interesting fact on how this tutorial came into being. Generally I eyeball and dry run most of the code on the forums, and hence when there is a long listing, I disregard that post, that's too much effort and a lot of redundancy. In some cases there is hardly any code provided which also makes it difficult to resolve.So while I was fixing the spelling errors (trying to be a spelling Nazi :( ) I understood what Jake was trying to do and he agreed for this to become a tutorial post. So, though the wrong reasons, it worked out quite well.. Thanks again Jake...
This is an AWESOME tutorial! It covers some key things one onEnterFrame events!
ReplyDelete