If you have your own tutorials or open source and would like to share your Director knowledge please send them to info@shocksites.com. We will review them, post it and give full credit to the developer.
Current Open Source and Tutorials

Download the Open Source Here

MENU

  1. Shockwave Sample
  2. IMAGE FEEDBACK
  3. HOW IT WORKS:
  4. BRUSH GRAPHIC
  5. FIRE LAYER
  6. DARKEN LAYER


IMAGING LINGO FIRE:
Provided by Zevan Renteren



This tutorial will show you how to create a classic fire effect with imaging lingo. Before taking this tutorial it might be beneficial for you to skim the Imaging Lingo Optimizations tutorial. If you aren't well versed in imaging lingo, you should definitely take Intro To Imaging lingo.

IMAGE FEEDBACK

The first technique we need to understand is an image feedback effect. This effect is achieved by copying an image into itself with blend and an offset. Enter this code into a frame script:

property myImage, stageRect

on beginSprite me

  myImage = image(50,50,32)

  -- fill myImage with dark and light blue
   myImage.fill(0,0,25,50,rgb(17,19,162))
   myImage.fill(25,0,50,50,rgb(3,138,242))

  -- store stageRect
   stageRect= (the stage).image.rect

end

on prepareFrame me

  -- draw myImage around the mouse
   (the stage).image.copyPixels(myImage, \
   rect(the mouseH-25, the mouseV-25, the mouseH+25, the mouseV+25), \
   rect(0,0,50,50))

  -- image feedback
   -- we offset both Vertical values of the destination rect
   (the stage).image.copyPixels((the stage).image, \
   rect(stageRect[1],stageRect[2]-6,stageRect[3],stageRect[4]-6), \
   stageRect,[#blendlevel:100])

end

Try it out.

If you weren't aware of this technique before, its likely that you'll want to go play with it for awhile and then come back to finish the tutorial.


HOW IT WORKS

The way the fire effect works is pretty simple. It consists of 2 image objects the size of the stage. The first one consists of yellow and red brush graphics being randomly placed at a very low opacity with a feedback effect:



We draw this image to the stage with #AddPin ink and apply the feedback effect. This creates the slightly blown out red and yellow colors:



The second image is comprised of anti-aliased black and white circles being randomly placed at very low opacity with a feedback effect. We draw this to the stage after the first image with a #SubtractPin ink. This erases the yellow and red colors at an uneven rate creating the tips of the flames:



Once applied, it looks like this:





BRUSH GRAPHIC
When drawing the yellow and red colors to the fire layer we use a brush graphic. We could create this graphic in photoshop, but its more fun to create one on the fly. Also, under certain circumstances creating images on the fly can shrink file size (this file is too small for it to really matter). Lets setup the dir:

We start off by creating a simple frame script and naming it "fire":

on beginSprite me
end

on prepareFrame me
end

Set the movie size to 400 x 300 and bump your movie fps to 60. Set the background color of your movie to black (this is very important).

Create a new vector member that looks like this:



Its a black circle about 50x50 pixles in size with no stroke. Name it "blackCircle". Now copy that member and rename it "whiteCircle". Edit the member and change its fill color from black to white. Your cast should look something like this:



We now want to take blackCircle and use it to create a brush graphic. We do this by duplicating it 20 times at a steadily increasing opacity. The final result will look like this:



We'll be doing some standard imaging setup. Replace your empty beginSprite handler with:

property stageRect -- rectangle of stage
property circleRect -- source rectangle for circles and brush
property bigCrect -- destination rectangle for brush
property yellowFlame -- yellow brush image
property bCircle -- black circle image (from vector member)
on beginSprite me

  -- store the stage rect
   stageRect = (the stage).image.rect

  -- duplicate image of blackCircle vector member
   bCircle=member("blackCircle").image.duplicate()

  -- store rect to be used with circle and brush images (source rect)
   circleRect=bCircle.rect

  -- create slightly larger rect to be used with brush images (destination rect)
   bigCrect= circleRect*1.5

  -- create the yellow brush
   yellowFlame=makeBrush( rgb(255,255,0) )

end

Notice that we call a handler called makeBrush at the end of the beginSprite handler. This is what will turn blackCircle into a brush graphic. Read through the comments carefully and copy the handler into your movie:

----------------------------------------------------
-- HANDLER for creating brushes
-- takes argument for color of brush
-- makeBrush( Color )
----------------------------------------------------
on makeBrush col

  -- create alpha channel image
   _alpha = image(bCircle.width,bCircle.height,8,#grayscale)

  -- fill with white
   _alpha.fill(0,0,bCircle.width,bCircle.height,rgb(255,255,255))

  -- draw alpha channel
   repeat with i = 1 to 20
    
     inc=inc+2
    
     -- scale rectangle smaller using inc value
     bCircleRect = rect(inc,inc,bCircle.width-inc,bCircle.height-inc)
    
     -- copy bCircle to _alpha slowly increasing blendlevel
     _alpha.copyPixels(bCircle,bCircleRect,circleRect,[#blendlevel:7*i])
    
   end repeat

  -- create brush image
   brush= image(_alpha.width,_alpha.height,32)
   -- fill with color
   brush.fill(0,0,_alpha.height,_alpha.width,col)

  -- enable brush image alpha channel
   brush.useAlpha=True

  -- set brush image alpha channel
   brush.setAlpha(_alpha)

  -- return brush image
   return brush

end

Lets test it out. Here is a prepareFrame handler that will draw the brush to the stage at random locations (Copy and paste to your script to see it in action.) :

on prepareFrame me

  -- temporary random x y values
   rx = random(320)
   ry = random(240)

  -- place brush on stage at a random position
   (the stage).image.copyPixels(yellowFlame, \
                                yellowFlame.rect+rect(rx,ry,rx,ry),\
                                yellowFlame.rect)
end

FIRE LAYER

If you understand everything we've covered here, the rest should be easy. We'll start by setting up our image object. Declare a variable called fireLayer:

property fireLayer -- lighten image

... and set it up in your beginSprite handler:

-- create image for fire (lighten layer)
   fireLayer = image(400,300,32)
   -- fill with black
   fireLayer.fill(0,0,400,300,rgb(0,0,0))

We also need a red brush and a black rectanlge graphic:

property redFlame -- red brush image
property black -- black rectangle image

... and on your beginSprite handler:

-- create red brush image
   redFlame=makeBrush( rgb(255,0,0) )

-- create black rectangle image 5px by 400 px
   black = image(400,5,32)
   -- fill with black
   black.fill(0,0,400,5,rgb(0,0,0))

Next, we need to repeatedly draw the brushes to fireLayer at random locations at a low opacity and then draw firelayer to the stage. To do this, you need to clear out your prepareFrame handler:

on prepareFrame me

end

And add the following code (read through the comments carefully):

----------------------------------------------------
   -- draw fire layer (lighten layer)
   ----------------------------------------------------

  -- draw brush strokes randomly:

  repeat with i = 1 to 3
    
     -- generate random coordinates
     rx=random(-50,400)
     ry=random(210,285)
    
     -- copy red brush image to fire layer with scale (bigCrect),
     -- random offset (rx,ry) and blend
     fireLayer.copyPixels(redFlame, bigCrect+rect(rx,ry,rx,ry), circleRect,[#blendlevel:10])
    
     -- re-generate random coordinates
     rx=random(-50,400)
     ry=random(210,285)
    
     -- copy yellow brush image to fire layer with scale (bigCrect),
     -- random offset (rx,ry) and blend
     fireLayer.copyPixels(yellowFlame, bigCrect+rect(rx,ry,rx,ry), circleRect,[#blendlevel:12])
    
   end repeat

  -- copy black rect to bottom of fire layer to prevent 2 much feedback
   fireLayer.copyPixels(black, rect(0,295,400,300), rect(0,0,400,5))

  -- copy fireLayer to fireLayer with vertical scale/offset and blend
   fireLayer.copyPixels(fireLayer,rect(0,-5,400,295),stageRect,[#blendlevel:190])

  -- copy firelayer to stage with lighten ink
   (the stage).image.copyPixels(fireLayer, \
   rect(random(-10,10),0,400,300), \
   stageRect,[#ink:#AddPin])

Test it out:



Next, we'll use the feedback technique described in the begining of the tutorial. This will spread the red and yellow colors upward and to the sides:

--------------------------------------------------
   -- feedback
   --------------------------------------------------

  -- copy stage image to stage image with vertical scale/offset
   (the stage).image.copyPixels((the stage).image, \
   rect(0,-5,400,298),stageRect)

  -- copy stage image to stage image with random horizonal scale/offset,
   -- vertical scale/offset and blend
   (the stage).image.copyPixels((the stage).image, \
   rect( random(-2,2),-2,400+random(-2,2),298), \
   stageRect,[#blendlevel:90])


Test it out again.



DARKEN LAYER
Lastly, we need to create the darken layer and draw it to the stage. This is what will create the tips of the flames. The code is similar to the firelayer code. First we need to setup the image objects:

property darkLayer
property wCircle

... then on you beginSprite handler:

-- create image for darken layer
   darkLayer = image(400,300,32)
   -- fill with black
   darkLayer.fill(0,0,400,300,rgb(0,0,0))

-- duplicate image of whiteCircle vector member
   wCircle=member("whiteCircle").image.duplicate()

The prepareFrame code is quite similar to the fire layer code. Take a look at the comments and then paste it in:

----------------------------------------------------
   -- draw darken layer
   ----------------------------------------------------

  -- draw brush strokes randomly:

  repeat with i = 1 to 10
    
     -- re-generate random coordinates
     rx=random(-40,410)
     ry=random(-40,230)
    
     -- copy white circle image to darken layer with random offset (rx,ry) and blend
     darkLayer.copyPixels(wCircle,circleRect+rect(rx,ry,rx,ry),circleRect,[#blendlevel:8])
    
     -- re-generate random coordinates
     rx=random(-40,410)
     ry=random(-40,250)
    
     -- copy black circle image to darken layer with random offset (rx,ry) and blend
     darkLayer.copyPixels(bCircle, circleRect+rect(rx,ry,rx,ry), circleRect,[#blendlevel:8])
    
   end repeat

  -- copy darkLayer to darkLayer with vertical scale/offset and blend
   darkLayer.copyPixels(darkLayer,rect(0,-2,400,280),stageRect,[#blendlevel:210])

  -- copy darkLayer to stage with SubtractPin ink
   (the stage).image.copyPixels(darkLayer,rect(random(-10,10),0,400,300),stageRect,[#ink:#SubtractPin])

Test it out:



Thats it. Now we have a classic fire effect.