Little plastic ArmyMan and Fire - AlphaBurner


A few post ago, a user asked how to make a plastic man interact with fire, and based on that I posted that if the users can try this an post their methods of achieving the same. Well, after a massive response of *no one* responding.... :(

The last post http://howto.oz-apps.com/2011/09/creating-interactive-object-using-lua.html

Jake volunteered to make a few graphics to get this started, His graphics are helpful and you have an interactive Game / Demo. Here's the video to demonstrate how it works.

Keep watching this space, i shall post (add the code) everyday till all of it exhausted and published.

local loqsprite = require('loq_sprite')
display.setStatusBar(display.HiddenStatusBar)

local _H = display.contentHeight
local _W = display.contentWidth

local idle
local speed = 4
local armyMan
local maxHealth = 100
local intensity = 5

local sky = display.newRect(0,0,_W, _H*.75)
local grad = graphics.newGradient({0,0,0},{6,44,100},"down")
sky:setFillColor(grad)
local ground = display.newRect(0,_H*.75,_W,_H*.25)
local grad = graphics.newGradient({66,30,0},{127,99,76},"down")
ground:setFillColor(grad)

local ffactory = loqsprite.newFactory("aniFlame01", "armyMan")
local flame = ffactory:newSpriteGroup()
flame.x = _W/2 ; flame.y = _H*.7
flame:play("aniFlame5 fire5")

How does it work

As you can see that we set quite a few variables and also set up the default values and rely on a third party script from Loqheart.

Lines 0001-0001 : We request that the code in the file loq_sprite
Lines 0002-0002 : Hide the status bar from appearing
Lines 0004-0005: We set defaults for the variables _W and _H which contain the screen width and the screen height
Lines 0006-0011: Now we define the variables that we will use, which are mostly used for attributing the time on the device.
Lines 0013-0018: These are the lines where we set up the sky, it's gradient, the ground, its gradient color.
Lines 0020-0014: These lines set up the factory object for creating a display animated object.

This is the code that i can share with the community for now, As the number of visitors to my site increase, I shall release more and more.

Part #2 - 17 Oct 2011

local healMe

function idle(self, _e)
 if _e.phase == "end" then
  flame:play("aniFlame5 fire5")
 end
end

flame.sprite = idle
flame:addEventListener("sprite", flame)

local healthRect = display.newRect(0,0,20,4)
 healthRect:setFillColor(0,255,0)

local healButton = display.newImage("heal.png",_W - 50,10)

local flameNo = display.newText("Fire Intensity : " .. intensity ,0,0,native.systemFontBold,32)
 flameNo:scale(0.5,0.5)
flameNo.y = 20
flameNo.x = _W/2

armyMan = ffactory:newSpriteGroup()
armyMan.x = _W/4
armyMan.y = 150
armyMan:scale(0.5,0.5)
armyMan.health = maxHealth
armyMan:play("armyMan armyMan")
Here's more code that adds functionality to the sample and the explanations for the same is

Lines 0001-0001: This is a forward declaration for a function we shall use later on to heal
Lines 0003-0007: Function called idle, this causes the animation to loop over
Lines 0009-0009: Set the sprite handler for the animation to idle
Lines 0010-0010: Add the event handler to the object
Lines 0012-0012: Create a new rectangle called healthRect which is 20 pixels x 4 pixels
Lines 0013-0013: Set the color of this rectangle to green
Lines 0015-0015: Create a new "Heal" Button which is an image called heal.png
Lines 0017-0017: Create a new Text object to show the flame intensity
Lines 0018-0018: Scale the text to half, for retina text/sharper text
Lines 0019-0019: Set the y position of the text to 20
Lines 0020-0020: Set the x position to the width/2 (center)
Lines 0022-0022: Create a new animated spriteGroup from the sprite factory
Lines 0023-0024: Set the x,y position for the ArmyMan as the starting position
Lines 0025-0025: Set the health value for the ArmyMan to 100
Lines 0026-0026: Start the animation for the ArmyMan


Part #3 - 18th Oct 2011

Let us write the code that will move the ArmyMan with our touch, i.e. we can drag and drop it anywhere we want on the screen

local function onTouch(event)
 local phase = event.phase
 local x = event.x
 local y = event.y
 local target = event.target
 
 if "began" == phase then
  display.currentStage:setFocus(armyMan)
  target.x0 = x
  target.y0 = y
  target.isFocus = true
 elseif "moved" == phase and target.isFocus==true then
  target.x = target.x + (x-target.x0)
  target.y = target.y + (y-target.y0)

  healthRect:setReferencePoint(display.TopLeftReferencePoint)
  healthRect.x = target.x + (target.contentWidth/2)
  healthRect.y = target.y - target.contentHeight

  target.x0 = x
  target.y0 = y  
 elseif "ended" == phase then
  display.currentStage:setFocus(nil)
  armyMan.isFocus = false
  target.x0 = nil
  target.y0 = nil
 end
end

Lines 0001-0001: This declares a function called onTouch
Lines 0002-0002: First we create local variables from the event object called Phase
Lines 0003-0004: Now we create the local x and y co-ordinates from the event's X and Y
Lines 0005-0005: and lastly we create the variable target, which is the armyMan itself
Lines 0007-0007: We check for the phase to see if it is the "began" phase
Lines 0008-0008: If it is, we set the focus to this object, all events will come to this object
Lines 0009-0010: we set two member vars x0 and y0 that hold the starting point of that event
Lines 0011-0012: and we set the isFocus flag to true
Lines 0013-0013: Otherwise we check for if the phase is "moved" and the object is the one with focus
Lines 0014-0015: we move the target to a new position by a relative distance of the start point and the event point
Lines 0016-0016: we set the referencePoint of the health bar to topLeft
Lines 0017-0018: We move this also relative to the armyMan, so that the health is on top, than floating elsewhere
Lines 0020-0021: Now we store the current event x, y in the previous x, y
Lines 0022-0022: Else if the event is "ended" we stopped touching the armyMan
Lines 0023-0023: First we set focus to nil, so that the armyMan stops getting all event messages
Lines 0024-0024: We set the isFocus flag to false
Lines 0025-0026: We set the previous points to nil

This function will move the armyMan around the screen smoothly and also move the healthBar along with him.

Part 4 - 21102011

For this part we shall look at the updateHealth function
local function updateHealth()
 local a_health = math.floor(armyMan.health,0)
  
  if a_health > 60 then
   armyMan:play("armyMan armyMan")
  elseif a_health > 40 then
   healthRect:setFillColor(0,255,0)
   armyMan:play("armyMan melting")
  elseif a_health > 20 then
   healthRect:setFillColor(180,180,0)
   armyMan:play("armyMan moreMelted")
  elseif a_health < 20 then
   armyMan:play("armyMan plasticBall")
   healthRect:setFillColor(255,0,0)
  end
  
  if a_health > 1 then 
   healthRect:setReferencePoint(display.TopLeftReferencePoint)
   healthRect.width = (a_health/5)
   --print(a_health)
  else
   healthRect:removeSelf()
   armyMan:removeSelf()
   armyMan=nil
   
   healButton:removeEventListener("tap",healMe)
  end
end

Lines 0001-0001: This is the function updateHealth, it takes no parameters
Lines 0002-0002: We declare a local variable a_health which is the rounded off health that our Armyman has
Lines 0004-0005: We start our cases, if the health is more than 60 then we play the animation of armyMan
Lines 0006-0008: Otherwise If the health is more than 40 then we play the animation of melting
Lines 0009-0011: Otherwise if the health is more than 20 then we play the animation of moreMelted and change the color to orange
Lines 0012-0014: Otherwise if the health is less than 20 then we play the animation of plasticBall and color the healthBar red
Lines 0017-0017: We check if the health is greater than 1, not yet completely disintegrated
Lines 0018-0019: we set the reference point to the TopLeft and change the healthbar width accordingly
Lines 0022-0024: Otherwise we remove the healthBar, the ArmyMan and set the armyMan to nil
Lines 0026-0026: We also disable the healMe button, since the armyman does not exist anymore.

Part 5 - 23 Oct 2011

Here's another batch of code this time we are dealing with the onEnterFrame part of the code which kind of hold the whole program together
local function onEnterFrame(event)
 if armyMan==nil then 
  Runtime:removeEventListener("enterFrame", onEnterFrame)
  return 
 end
 if armyMan.isFocus==true then return end

 healthRect.x = armyMan.x + (armyMan.contentWidth/2)
 healthRect.y = armyMan.y - armyMan.contentHeight
  

 if armyMan.y < (_H *.95) then
  armyMan.y = armyMan.y+speed
 elseif armyMan.x >186 and armyMan.x < 266 then
  armyMan.health = armyMan.health - (0.1 * intensity)
  updateHealth()
 else
  healthRect.x = armyMan.x + (armyMan.contentWidth/2)
  healthRect.y = armyMan.y - armyMan.contentHeight
 end

end
Lines 0001-0001 : This is the function onEnterFrame that is the handler for enterFrame
Lines 0002-0005 : If the armyMan has been removed i.e. melted, we remove the event Listener too
Lines 0006-0006 : if we are moving the armyMan, then we ignore doing anything to it
Lines 0008-0009 : we move the healthRect relative to the armyMan
Lines 0012-0013 : We check where the armyMan is at this point, if he is in the first 95% of the screen then we move him down as if it was a physics body
Lines 0014-0016 : if armyMan is between 186 and 266 (on fire), reduce health by the Intensity * 0.1
Lines 0018-0019 : Once again we move the health bar relative to the armyMan

Part 6 - Oct 25

The final part is here....

local function changeIntensity(event)
 intensity = intensity + 1
 if intensity > 5 then intensity = 1 end
 flameNo. text = "Fire Intensity : " .. intensity
end

function healMe(event)
 armyMan.health = math.floor(armyMan.health + 10)
 if armyMan.health > 100 then armyMan.health = 100 end
 updateHealth()
end

healButton:addEventListener("tap",healMe)
flameNo:addEventListener("tap",changeIntensity)
armyMan:addEventListener("touch",onTouch)
Runtime:addEventListener("enterFrame",onEnterFrame)

This is rather simple to understand...

We have a function called changeInstensity and this cycles through the intensity, increasing it by 1 and when it goes beyond the max (5) it is set to 1 again. This also displays the text and shows us what the current intensity is.

Then we have another function healMe, this one just adds 10 to the health and if the health reaches maximum, it keeps it at that, otherwise we can keep increasing it and the health bar will keep on increasing, not what we would want.

the last four lines set the eventHandlers for tap on the healButton and the flameNo, which trigger the healMe and the changeIntensity what we had a look at above, and a touch event handler for armyMan which will invoke the onTouch function above in Part#3. Lastly we add a enterFrame event handler which has the obEnterFrame as defined in Part#5 above.

Well that is all there is to the code of this example.

all of it together than in pieces, if you want to cut/paste it
local loqsprite = require('loq_sprite')
display.setStatusBar(display.HiddenStatusBar)

local _H = display.contentHeight
local _W = display.contentWidth

local idle
local speed = 4
local armyMan
local maxHealth = 100
local intensity = 5

local sky = display.newRect(0,0,_W, _H*.75)
local grad = graphics.newGradient({0,0,0},{6,44,100},"down")
sky:setFillColor(grad)
local ground = display.newRect(0,_H*.75,_W,_H*.25)
local grad = graphics.newGradient({66,30,0},{127,99,76},"down")
ground:setFillColor(grad)

local ffactory = loqsprite.newFactory("aniFlame01", "armyMan")
local flame = ffactory:newSpriteGroup()
flame.x = _W/2 ; flame.y = _H*.7
flame:play("aniFlame5 fire5")

function idle(self, _e)
 if _e.phase == "end" then
  flame:play("aniFlame5 fire5")
  --flame:removeEventListener("sprite", flame)
 end
end

local healMe

flame.sprite = idle
flame:addEventListener("sprite", flame)

local healthRect = display.newRect(0,0,20,4)
 healthRect:setFillColor(0,255,0)

local healButton = display.newImage("heal.png",_W - 50,10)

local flameNo = display.newText("Fire Intensity : " .. intensity ,0,0,native.systemFontBold,32)
 flameNo:scale(0.5,0.5)
 --flameNo:setTextColor(0,0,0)
flameNo.y = 20
flameNo.x = _W/2

armyMan = ffactory:newSpriteGroup()
armyMan.x = _W/4
armyMan.y = 150
armyMan:scale(0.5,0.5)
armyMan:play("armyMan armyMan")
armyMan.health = maxHealth

local function onTouch(event)
 local phase = event.phase
 local x = event.x
 local y = event.y
 local target = event.target
 
 if "began" == phase then
  display.currentStage:setFocus(armyMan)
  target.x0 = x
  target.y0 = y
  target.isFocus = true
 elseif "moved" == phase and target.isFocus==true then
  target.x = target.x + (x-target.x0)
  target.y = target.y + (y-target.y0)

  healthRect:setReferencePoint(display.TopLeftReferencePoint)
  healthRect.x = target.x + (target.contentWidth/2)
  healthRect.y = target.y - target.contentHeight

  target.x0 = x
  target.y0 = y  
 elseif "ended" == phase then
  display.currentStage:setFocus(nil)
  armyMan.isFocus = false
  target.x0 = nil
  target.y0 = nil
 end
end

local function updateHealth()
 local a_health = math.floor(armyMan.health,0)
  
  if a_health > 60 then
   armyMan:play("armyMan armyMan")
  elseif a_health > 40 then
   healthRect:setFillColor(0,255,0)
   armyMan:play("armyMan melting")
  elseif a_health > 20 then
   healthRect:setFillColor(180,180,0)
   armyMan:play("armyMan moreMelted")
  elseif a_health < 20 then
   armyMan:play("armyMan plasticBall")
   healthRect:setFillColor(255,0,0)
  end
  
  if a_health > 1 then 
   healthRect:setReferencePoint(display.TopLeftReferencePoint)
   healthRect.width = (a_health/5)
   --print(a_health)
  else
   healthRect:removeSelf()
   armyMan:removeSelf()
   armyMan=nil
   
   healButton:removeEventListener("tap",healMe)
  end
end

local function onEnterFrame(event)
 if armyMan==nil then 
  Runtime:removeEventListener("enterFrame", onEnterFrame)
  return 
 end
 if armyMan.isFocus==true then return end

 healthRect.x = armyMan.x + (armyMan.contentWidth/2)
 healthRect.y = armyMan.y - armyMan.contentHeight
  

 if armyMan.y < (_H *.95) then
  armyMan.y = armyMan.y+speed
 elseif armyMan.x >186 and armyMan.x < 266 then
  armyMan.health = armyMan.health - (0.1 * intensity)
  updateHealth()
 else
  healthRect.x = armyMan.x + (armyMan.contentWidth/2)
  healthRect.y = armyMan.y - armyMan.contentHeight
 end

end

local function changeIntensity(event)
 intensity = intensity + 1
 if intensity > 5 then intensity = 1 end
 flameNo. text = "Fire Intensity : " .. intensity
end

function healMe(event)
 armyMan.health = math.floor(armyMan.health + 10)
 if armyMan.health > 100 then armyMan.health = 100 end
 updateHealth()
end

healButton:addEventListener("tap",healMe)
flameNo:addEventListener("tap",changeIntensity)
armyMan:addEventListener("touch",onTouch)
Runtime:addEventListener("enterFrame",onEnterFrame)

I will be blunt and honest, it does take a lot of time and effort to create stuff like this, it does not help when there are not many hits, If this meets a similar fate of low number of hits, then I will have to close the site and/or make it Subscription based, whether free or for a small fee will be determined later. For those that are reading this, I know you are here, it is the others... I shall post the entire code when this reached 100 hits, The last game I posted, Bug Catcher, I have had only 45 hits so far... not impressed... Since I am not in for the Analytics money or any such stuff, I do not have to lie and tell that there were close to a million hits on the site... like other sites have to. I will send the code to the few regulars that I know on first name basis if they request for it, you know where to ask...
I guess this will be the last free tutorial related to CoroanSDK for the community... I thank those that were there as support and were regular viewers. For the others, that might come to this one day when they find a link like with the PropertyBag, which a lot of people ask for now. Well, too bad and a bit too late. This is the last post with an actual app or tutorial till things change. If you are interested in sponsoring the running of the site with your services/Ads, please get in touch with me.

cheers,

?:)

Comments

Post a Comment

Popular Posts