Main Menu

Particle Candle

Started by kevin, May 21, 2008, 02:58:30 PM

Previous topic - Next topic

kevin

 Particle Candle

   This example manually plots some particles (sprites) to simulate a lit candle.  

    Code attached at bottom of post with MEDIA,  written for PlayBASIC V1.63.


   

Video:


   
 


  This code is a PlayBASIC program that displays a candle on the screen and creates particle effects that simulate flames. The program uses the "blitimage" library to manipulate images and sprites.

The program starts by loading an image of a candle and blurring it slightly. It also loads an image of a flare to be used as a particle. A FX screen is created to avoid fetching pixels from the backbuffer.

The program then enters a loop that continuously updates the screen. In each iteration, the candle image is drawn on the screen, and new particles are spawned at the position of the mouse cursor when the left mouse button is pressed. The color of the particles is randomly chosen as a red/yellow tint.

The particle effects are implemented using a list of "tParticle" objects, which store information about the particle's sprite, image, color, lifetime, and other properties. The program updates the position, color, and scaling of each particle over time based on its lifetime.

The program also allows the user to change the "screen fade/tint color" by pressing the right mouse button. The screen color is changed to a random color. Additionally, the program applies a screen fade/tint effect on the screen.

Finally, the program uses the "Sync" function to synchronize the framerate of the animation to 60 FPS. The loop continues indefinitely until the program is closed.



PlayBASIC Code: [Select]
---------------------------------------------


#Include "blitimage"

SetFPS 60

Type tParticle
Sprite
ParticleImage
Colour
LifeTime
LifeSTartTime
LifeEndTime
NextRefresh
Speed#
Scale#
EndType

// Dim the particle list
Dim Particle as tParticle List


// Load the candle image + scale blur it a little
CandleImage=LoadnewFXimage("gfx/candle.jpg")
Scaleimage CandleImage,2,2,0
BlurImage CandleImage,8.5

ParticleImg=LoadnewFXimage("gfx/flare.png")


; use a FX screen to avoid fetching pixels from backbuffer (which is in video memory)
Screen=NewFXImage(GetScreenWidth(),GetScreenHeight())


TimeProgramStarted=Timer()

// SCreen Tint/Fade Colour
ScreenFadeColour=$ffffff

Do

RenderToImage Screen
; Clear the screen buffer
cls Rgb(0,0,0)

Xpos=GetScreenWidth()/2-GetImageWidth(CandleImage)/2
Ypos=GetScreenHeight()-GetImageHeight(CandleImage)
DrawImage CandleImage,Xpos,Ypos,false


// Pick a redy/yellow colour to tint each flame particle
r=rndrange(40,120)
g=rndrange(20,60)
b=rndrange(0,20)
SpawnParticle(ParticleImg,392,310,rgb(r,g,b))


// Spawn a particle at the mouse position
if LeftMouseButton()
SpawnParticle(ParticleImg,Mousex(),mousey(),rndrgb())
endif

; Change the 'Screen fade/Tint colour' just for something to look at :)
if RightMousebUtton()
ScreenFadeColour=rndrgb()
endif

// Refresh the particle list
CurrentTime=timer()
For Each Particle()

Spr=Particle.Sprite
ThisImage=GetSpriteIMage(spr)

if CurrentTime=>particle.LifeEndTime
DeleteImage Thisimage
DeleteSprite Spr
Particle =null
else

TimePassed#=CurrentTime-Particle.LifeStartTime

if CurrentTime>Particle.NextRefresh
Particle.NextRefresh=CurrentTime+100
Scale#=(TimePassed#/Particle.LifeTime)*100
Scale#=100-ClipRange#(Scale#,0,100)
Colour=RgbFade(Particle.Colour,Scale#)
RenderToImage ThisImage
BlitImageAlphaMultColour(Particle.ParticleImage,0,0,Colour)
endif

Speed#=(Timepassed#/Particle.LifeTime)*Particle.Speed
Speed#=Particle.Speed-ClipRange#(Speed#,0,Particle.Speed)
MoveSprite Spr,0,-Speed#

Scale#=(Timepassed#/Particle.LifeTime)*Particle.Scale
Scale#=Particle.Scale-ClipRange#(Scale#,0,Particle.Scale)
ScaleSprite Spr,0.45+Scale#
endif
next

RenderToImage Screen

// Draw this batch of sprite in one hit
DrawAllSprites

// Restore rendering to the back buffer
RenderToScreen

// Do Screen Fade/Tint
Ticks=Timer()-TimeProgramStarted
Ticks=mod(Ticks,10000)
angle#=Ticks*(360/10000.0)
Scale#=50+Sin(angle#)*50
Scale#=cliprange#(scale#,0,100)

// move & colour the Screenimage to the backbuffer
BlitImageAlphaMultColour(Screen,0,0,RgbFade(ScreenFadeColour,Scale#))

Sync
loop



Function SpawnParticle(ParticleImg,Xpos,Ypos,Colour)
// Get the source images size
Width =GetImageWidth(ParticleIMG)
Height =GetImageHeight(ParticleIMG)

// Spawn temp cache image
ThisIMage=NewFXimage(Width,Height);
RenderToImage ThisImage
result=BlitImageAlphaMultColour(ParticleImg,0,0,Colour)
RenderToScreen

// Create a sprite and assign the draw mode
Spr=newSprite(xpos,ypos,ThisIMage)
SpriteDrawmode spr,2+16
ScaleSprite Spr,rndrange#(0.15,0.45)

CenterSpriteHandle spr

Particle = new tParticle
Particle.sprite =spr
Particle.ParticleImage =ParticleIMg
Particle.Colour =Colour

Particle.LifeTime=rndrange(1000,1800)
Login required to view complete source code







Music:


     Vitality - By Benjamin Martins



 Download (attached):

Adaz

Superb, totally reminds me to Cadaver on Amiga :-)

Ádáz

Hungary

ATLUS

 :o cool!!!!!!!!!!!!!!!!!!

thaaks

Yeah, looks great and pretty similar to Crystal Noir's PureBasic example.

Although I must say that using a combination of SpriteDrawModes (2+4+16 or 2+4+2048) and calling the appropriate functions SpriteAlphaLevel, SpriteFadeLevel, SpriteAlphaColour seems much more intuitive and simpler to me than using BlitImageAlphaMultColour() and storing a separate image for each particle sprite...
This is a much more low level solution if you know what I mean  :-\

But thanks for this source code, at least we now know how to deal with those blending combinations  ;)

Cheers,
Tommy

Crystal Noir

Great effect :)

Not a real time effect (cf thaaks) but good particle effect :)

Perhaps the solution is to "attack" the 3D sprite structures in the 1.70 version to have real time lightning effect.

this code is a good example to simulate lightning effects :)

Thx :)

kevin


QuoteNot a real time effect

It is real time.

kevin


QuoteAlthough I must say that using a combination of SpriteDrawModes (2+4+16 or 2+4+2048)

   Combining those modes does not give the above effect.   The so called 'lighting' effect is vertex colouring, which requires texel multiplication.  V1.63 doesn't have a mult mode in the sprite filler.

   Described  here



thaaks

Quote from: kevin on May 22, 2008, 10:02:05 PM
Combining those modes does not give the above effect.   The so called 'lighting' effect is vertex colouring, which requires texel multiplication.  V1.63 doesn't have a mult mode in the sprite filler.
Oh, I thought that this SpriteAlphaColour function would give the same effect. My fault.

Crystal Noir

Quote from: kevin on May 22, 2008, 10:02:05 PM

QuoteAlthough I must say that using a combination of SpriteDrawModes (2+4+16 or 2+4+2048)

   Combining those modes does not give the above effect.   The so called 'lighting' effect is vertex colouring, which requires texel multiplication.  V1.63 doesn't have a mult mode in the sprite filler.

   Described  here

Yes this the technic I use in Pure to have my candle effect, vertex colouring ^^

kevin

#9
 Particle Candle

   This is the same example as the one above, updated for PlayBASIC V1.64/ V1.65 editions.     (Learning Edition and Retail)

  The main difference is the use of the SpriteTint function to colour the sprite pixels in so called 'real time' whatever that is.