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.
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
-- 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:
-- 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:
-- 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])