Have a look at this method. Although it uses pixmaps the method used to set the pixels is really fast
(The demo only seems to work in non-debug mode for me though)
Rem
Binary Therapys Fire Demo
Mods (Jim Brown):
Stripped dependancies
EndRem
Strict
Framework BRL.GLMax2D
'Framework BRL.D3D7Max2D
Import BRL.Bank
Import BRL.Random
Import BRL.BMPLoader
SetGraphicsDriver GLMax2DDriver()
'SetGraphicsDriver D3D7Max2DDriver()
Global particle_list:TList=New TList
Const glevel1=1
Const glevel2=2
Const glevel3=4
Const maxx=239
Const maxy=239
Const particle_life=1000
Global firepix:TPixmap=CreatePixmap(480 , 480 , PF_RGBA8888)
Global cfb:TBank = CreateBank(57600)
Global hfb:TBank = CreateBank(57600)
Global creds=0
SeedRnd MilliSecs()
AppTitle = "BlitzMax Firedemo"
Global quittime=0
Global qta=1
Global gradient[256] , col[5]
col[0]=$000000
col[1]=$400040
col[2]=$000080
col[3]=$C00000
col[4]=$FFFF00
SetupGradient()
Graphics 640,480 , 32
Local angl:Double = 0
Type Particle
Field x#,y#
Field speed#,direction,angle,life
Global pcount=0
Method New()
x=0
y=0
speed#=Rnd (.2 , .6)
direction=Rand(0,359)
angle=direction
life=particle_life
pcount:+1
particle_list.AddLast(Self)
End Method
Method Update()
If x < -120 Then x = -120
If x > 119 Then x = 119
If y < -120 Then y = -120
If y > 119 Then y = 119
Local bofs= Int(x+120) + Int(y+120)*240
Local myPtr:Byte Ptr = BankBuf (cfb)
Local valu=myPtr[bofs]
valu=valu+20
If valu<80
life:-1
EndIf
If life <=0
x=0
y=0
speed#=Rnd (.2 , .6)
direction=Rand(0,359)
angle=direction
life=particle_life
Else
If valu>255 Then valu=255
myPtr [bofs] = valu
Local surfangle = ATan2 ( y , x )
x = x + speed * Cos( direction )
y = y + speed * Sin( direction )
If (x*x + y*y)>10000
angle = surfangle - 180
Else
If angle = direction
angle=Rand(0,359)
EndIf
EndIf
angle=(angle + 360) Mod 360
direction=(direction + 360) Mod 360
Local angc:Double
If angle<direction
angc=360+angle-direction
Else
angc=angle-direction
EndIf
If angc>180
direction=direction-1
ElseIf angc>0
direction=direction+1
EndIf
EndIf
EndMethod
End Type
' #####################################
Repeat
Flip False
Cls
Local startime = MilliSecs()
For Local p:Particle = EachIn particle_list
p.update
Next
For Local yco=0 To maxy
For Local xco=0 To maxx
Local myPtr:Byte Ptr = BankBuf(cfb)
Local rb:Byte = myPtr [xco + yco*240]
If rb>0
Local valu=rb*glevel3
Local x1 = xco-1
If x1<0 Then x1=x1+maxx
Local x3 = xco+1
If x3>maxx Then x3=x3-maxx
Local y1 = yco-1
If y1<0 Then y1=y1+maxy
Local y3 = yco+1
If y3>maxy Then y3=y3-maxy
rb=myPtr [x1 + y1 * 240]
valu=valu+rb*glevel1
rb=myPtr [xco + y1 * 240]
valu=valu+rb*glevel2
rb=myPtr [x3 + y1 * 240]
valu=valu+rb*glevel1
rb=myPtr [x1 + yco * 240]
valu=valu+rb*glevel2
rb=myPtr [ x3 + yco * 240 ]
valu=valu+rb*glevel2
rb=myPtr [x1 + y3 * 240]
valu=valu+rb*glevel1
rb=myPtr [xco + y3 * 240]
valu=valu+rb*glevel2
rb=myPtr [x3 + y3 * 240]
valu=valu+rb*glevel1
valu=valu Shr 4
PokeByte hfb,xco + yco * 240 , valu
EndIf
Next
Next
For Local yco=0 To maxy
For Local xco=0 To maxx
Local bofs=yco*240+xco
Local valu=PeekByte(hfb,bofs)
If valu>0
If valu>4
valu=valu-4
Else
valu=0
EndIf
PokeByte hfb,bofs,valu
WritePixel firepix , xco*2 , yco*2 , gradient[valu]
WritePixel firepix , xco*2+1 , yco*2 , gradient[valu]
WritePixel firepix , xco*2+1 , yco*2+1 , gradient[valu]
WritePixel firepix , xco*2 , yco*2+1 , gradient[valu]
EndIf
Next
Next
Local temp:TBank = cfb
cfb = hfb
hfb = temp
DrawPixmap firepix , 80 , 0
angl=angl+12.5
If angl>180 Then angl=angl-180
Local frametime=MilliSecs()-startime
If frametime<30 And qta>0
For Local i = 0 To 9
New Particle
Next
EndIf
If Particle.pcount>0
Local part:String="Featuring "+Particle.pcount+" real-time blurred particles."
DrawText part , 30,0
EndIf
If KeyHit(KEY_ESCAPE) And quittime=64
particle_list.Clear()
Particle.pcount = 0
quittime=63;qta=-qta
EndIf
If quittime<64
quittime=quittime+qta
EndIf
While frametime<33
frametime=MilliSecs()-startime
Wend
Until quittime=0 And qta < 0
End
Function SetupGradient()
Local ofs,grad,i
While ofs<255
For i=0 To 63
Local perc#=i/63.0
Local x1=col[grad] Shr 16 & $FF
Local xco=col[grad] Shr 8 & $FF
Local x3=col[grad] & $FF
Local y1=col[grad+1] Shr 16 & $FF
Local yco=col[grad+1] Shr 8 & $FF
Local y3=col[grad+1] & $FF
gradient[i+ofs]=$FF000000 + Int(x1*(1-perc)+y1*perc) Shl 16 + Int(xco*(1-perc)+yco*perc) Shl 8 + Int(x3*(1-perc)+y3*perc)
Next
ofs=ofs+i;grad=grad+1
Wend
EndFunction
There is also a faster version of drawing a pixmap to the screen too (OpenGL):
Function FastDrawPixmap(p:TPixmap,x,y,scalex#=1.0, scaley#=1.0)
Local blend%=GetBlend()
glDisable GL_TEXTURE_2D 'DisableTex
SetBlend SOLIDBLEND
Local t:TPixmap=p
If t.format<>PF_RGBA8888 t=ConvertPixmap(p, PF_RGBA8888 )
glpixelzoom scalex#,-scaley#
glRasterPos2i 0,0
glBitmap 0,0,0,0,x,-y,Null
glPixelStorei GL_UNPACK_ROW_LENGTH, p.pitch Shr 2
glDrawPixels p.width, p.height, GL_RGBA, GL_UNSIGNED_BYTE, p.pixels
glEnable GL_TEXTURE_2D
SetBlend blend
End Function