ООО "МСК" Очистка поверхностейУборка после пожара
ООО "МСК" Очистка поверхностейОчистка после пожара
ООО "МСК" Очистка поверхностейОчистка от краски

Effect "Flame"

Written by kaldirishe on . Posted in Blog

Lightbox Image

Effect "Flame"

In the new version of library the new effect – a flame was added. The effect is made on quite trivial algorithm of smoothing. It works as follows – the color palette is created, the massif of values by dimension in the image is created, indignations are brought in the massif and further are averaged. At effect it is some properties: 5 flowers, the 3rd positions of transitions of flowers (between the 2nd and 3rd color, the 3rd and the 4th, the 4th and the 5th), intensity of indignations, degree and type of transparency, coordinate. All properties except type of transparency can be animated. At flowers it is possible to animate ARGB components. During experiments at the choice of properties the most realistic flame turns out at the following set:

  • colors: white, white, yellow, red, black;
  • transition positions: 60, 30, 10 (in the sum have to be equal 100);
  • intensity of indignation: 1 (I will animate this size)
  • transparency degree: 1;
  • transparency type: the square. 

Kindling and extinction is realized by animation of intensity of indignation from 0 to 1 and back. 
Besides the class of effect there are two auxiliary classes of settings – initialization and cleaning. The first sets the sizes of the image of the flame, the second clears the image. Couple of words about the animation, at effect Count property of the byte type, that is quantity of steps for which the flame will burn is provided. 255 steps "will burn through" for some seconds therefore effect I will loop. Probably two options, the first on the timer, the second – using effect of generation of an event. Both work, but with the timer is somehow more evident. Well and the last, I specially added to a component some office OnSystem properties in order that on them it was possible to hang up effects and necessarily to switch over between them.

So we will start Smile

Step 1

We create the project, we throw on a form: TlfeLayerForm, TlfeBitmapsList, TlfeLayerEffectList, 4 TlfeLayerEffectControl, TTimer, TPopupMenu.

Lightbox Image

lfeLayerEffectControl1 will be a fireplace (size 237, 239 and DragAble=True), lfeLayerEffectControl2 and lfeLayerEffectControl3 - candles (size 25, 60), lfeLayerEffectControl4 an icon. I put Timer.Enable in False and Interval in 10. I create at PopupMenu1 - TMenuItem, and in an event of OnClick I write Close. I appropriate lfeLayerEffectControl1.PopupMenu - PopupMenu1. I connect library components among themselves: lfeLayerEffectList1.Images - lfeBitmapsList1, lfeLayerEffectList1.LayerForm - lfeLayerForm1; for all TlfeLayerEffectControl - lfeLayerEffectControl.LayerEffectList - lfeLayerEffectList1, lfeLayerEffectControl.LayerForm - lfeLayerForm1. Into lfeBitmapsList1 I load images of a fireplace and an icon (I choose Images property in the inspector, further in the Add dialog box), it is possible to download here.

Step 2

I start adjusting animation (I choose Collection property at lfeLayerEffectList1 in the inspector). I tie effect to lfeLayerEffectControl1, I tie an event to "OnDesigned", I bind a step, I add to a step: "To clear a canvas", "To clear a component", "To draw on a canvas" and "To draw a component". At the first two I expose lfataInit in True, at the third I select the fireplace image, at the fourth I expose lfetaAnimate in True.

Lightbox Image 

Step 3

I copy an event on "OnLoaded" and "OnSystem1" event. In "Step 1" at an event of "OnSystem1" I add "to Add 'flame'", I move it on the ode a position up and I adjust: 

Lightbox Image  Lightbox Image  Lightbox Image

Color2 properties. Color5 are adjusted similar to Color1, but taking into account a color choice (respectively as an order of components in properties of ABGR color: (255,255,255,255) (255,0,255,255) (255,0,0,255) (255,0,0,0)) . Intensity yet I don't touch. Work tiresome, but becomes once. I copy "OnSystem1" event on "OnSystem2", "OnSystem3", "OnSystem4". I come back to  "OnSystem1" and I add three more steps. In the first added I add "to Initialize 'Flame'" and I specify the Width=120 Height=100 sizes, in the second I add "to Remove 'Flame'" and I insert lfataInit into True, in the third I add effect "to Process". Now I move "Step 1" down on two positions (has to become the third):

Lightbox Image

 

I draw Intensity at effect of an event of "OnSystem1": initial value 0, final 1, type of initialization of tivValue, with animation for 200 steps (the flame will inflame):

Lightbox Image 

At events of "OnSystem2", "OnSystem3": initial value 1, final 1, type of initialization of tivValue, without animation (the flame burns). At "OnSystem4" events: initial value 1, final 0, type of initialization of tivValue, with animation in 200 steps (the flame goes out). Also the structure so looks:

Lightbox Image

Well and at last I will loop animation. I choose on the lfeLayerEffectControl1 form and I create responses to "OnMouseUp" and "OnSystem1" (in passing I connect PopupMenu1):

Lightbox Image 

and respectively I fill them:

procedure TForm1.lfeLayerEffectControl1MouseUp (Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if Button = mbRight then lfeLayerEffectControl1.PopupAtCursor;
end;

procedure TForm1.lfeLayerEffectControl1System1 (Sender: TObject);
begin
Timer1.Enabled: = True;
end;

Step 4

The fastest sequence of control of animation of candles from my point of view is following:

  • I copy all tree a tree of effects of the lfeLayerEffectControl1 component on the lfeLayerEffectControl2 component. I choose lfeLayerEffectControl2. As except a flame of any images it isn't meant - I delete bindings to "OnDesigned" and "OnLoaded" events. I choose "OnSystem1", in the first step at effect of initialization of a flame I change the size on 25,60, and in the third step I delete effect "To draw on a canvas". At effect of a flame I increase final intensity with 1 to 3 (that is will inflame with 0 to 3) and I expose X and Y in 0,0 (initial and final values). I delete the fourth step with event processing. 
  • In events of "OnSystem2", "OnSystem3" similarly in the first step I delete "To draw on a canvas", I change intensity with 1 on 3 and I expose X and Y in 0,0 (initial and final values).
  • In "OnSystem4" similarly I delete "To draw on a canvas", I change initial intensity with 1 on 3, that is will be to fade with 3 to 0 and I expose X and Y in 0,0 (initial and final values). Also the structure so looks:

Lightbox Image  

  • I copy all tree a tree of effects of the lfeLayerEffectControl2 component on the lfeLayerEffectControl3 component. 

Now I will adjust lfeLayerEffectControl4. I copy all tree of effects of the lfeLayerEffectControl1 component on the lfeLayerEffectControl4 component. I choose lfeLayerEffectControl4 and I delete bindings to "OnSystem1" events. "OnSystem4". In "OnDesigned" and "OnLoaded" events at effect "To draw on a canvas" I select the image of an icon of a flame. I copy "OnDesigned" event on "OnMouseEnter" and "OnMouseLeave" events. I add in "Step 1" of an event of "OnMouseEnter" - "To dump a matrix of flowers" and "To change color". For the first I expose lfataInit in True. For the second I expose red color (255,0,0,255). I add in "Step 1" of an event of "OnMouseLeave" - "To dump a matrix of flowers". I expose lfataInit in True.

Lightbox Image

 

I will create and will fill a response to "OnMouseUp" event in the inspector a component:

procedure TForm1.lfeLayerEffectControl4MouseUp (Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
Timer1.Enabled: = False;

with lfeLayerEffectControl1 do
if (CurrentEventName = 'OnLoaded') or
(CurrentEventName = 'OnSystem4') then
GenerateEvent ('OnSystem1')
else
GenerateEvent ('OnSystem4');

with lfeLayerEffectControl2 do
if (CurrentEventName = 'OnLoaded') or
(CurrentEventName = 'OnSystem4') then
GenerateEvent ('OnSystem1')
else
GenerateEvent ('OnSystem4');

with lfeLayerEffectControl3 do
if (CurrentEventName = 'OnLoaded') or
(CurrentEventName = 'OnSystem4') then
GenerateEvent ('OnSystem1')
else
GenerateEvent ('OnSystem4');
end;

I will fill the handler of the timer and a menu:

procedure TForm1.Timer1Timer (Sender: TObject); 
begin
if lfeLayerEffectControl1.CurrentEventName = then 'OnSystem2'
begin
lfeLayerEffectControl1.GenerateEvent ('OnSystem3');
lfeLayerEffectControl2.GenerateEvent ('OnSystem3');
lfeLayerEffectControl3.GenerateEvent ('OnSystem3');
end
else
begin
lfeLayerEffectControl1.GenerateEvent ('OnSystem2');
lfeLayerEffectControl2.GenerateEvent ('OnSystem2');
lfeLayerEffectControl3.GenerateEvent ('OnSystem2');
end;
end;

procedure TForm1.Close1Click (Sender: TObject);
begin
Close;
end;

As a postscript: it was possible to loop animation also next way - in "OnSystem2" and "OnSystem3" events (all components with flame animation) it is necessary to add effect "to Generate" a step, and to it at which to expose lfataInit in True and EventName = OnSystem3 for "OnSystem2" event and vice versa. At effect of a flame to expose Count in 100. 255 . And to replace effect "to Process" (an event of "OnSystem1", "Step 4") at lfeLayerEffectControl1 on "to Generate" with the indication of an event of "OnSystem2".

It is possible to download an example here

Add comment


Security code
Refresh