It is currently Tue May 21, 2013 11:00 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 15 posts ] 
Author Message
 Post subject: Fireworks
PostPosted: Wed May 25, 2011 3:21 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Thu Mar 24, 2011 12:40 am
Posts: 155
Location: Iowa, USA
Hello everyone, this is my first post to the forum.
I thought I'd start things off with a 'Bang' so to speak.

A bit about myself, I am a hobby programmer and have returned to programming after a period of many years without writing any code.
For the last couple of years I have been trying to catch up.
Programming has changed (a lot) since my first computing days before Windows was an operating system.

I have been using PureBasic for about three months and am very pleased with it so far.
This forum has been very useful in answering many questions I have had as a beginner.

The program I am posting here is one I wrote in a different Basic and have translated to PureBasic.
Press 'Escape' when you want it to end.

BP

Code:
;fireworks by BasicallyPure
;05/24/2011
;PureBasic v4.51 (x86)

If Not InitSprite() Or Not InitKeyboard() : End : EndIf
ExamineDesktops()
ScreenWidth = DesktopWidth(0)
ScreenHeight = DesktopHeight(0)

;{ constant declarations
#Color_Blue = $FF0000
#Color_Red = $0000FF
#Color_Green = $00FF00
#Color_Yellow = $00FFFF
#Color_White = $FFFFFF
#Color_Cyan = $FFFF00
#Color_Pink = $FF00FF
#Color_Black = $000000
;}

Declare.f RandFloat()

;{ variable declarations
Define.l max = 600 ; This sets the size of the ember array
Define.l fuse = 0 ; countdown timer until next burst
Define.l ode = 0 ; index to oldest ember
Define.l youngest = -1 ; index to youngest ember
Define.f drag = 0.91 ; 0 < drag < 1; smaller = more drag
Define.f gravity = 0.1, pow, alfa
Define.f tupi = 2*#PI
Define.l midx = ScreenWidth / 2 ; middle of screen
Define.l devx = midx * 0.75 ; maximum x deviation from center
Define.l nomy = ScreenHeight * 0.45 ; nominal y location
Define.l devy = ScreenHeight * 0.25 ; maximum y deviation from nomy
Define.l a, n, embers, cmix, c1, c2, shape

Dim rm.f(max,3) ;array for erasing previous embers
Dim em.f(max,5) ;this is the ember array
   ;legend for em(n,n) array
     ;em(n,0) = x coordinate of ember
     ;em(n,1) = y coordinate of ember
     ;em(n,2) = x velocity of ember
     ;em(n,3) = y velocity of ember
     ;em(n,4) = color of ember
     ;em(n,5) = lifetime of ember
   ;end legend

Dim color.l(6) ;colors for embers
color(0)= #color_red : color(1)=#Color_Cyan : color(2)=#Color_Pink
color(3)=#Color_White : color(4) = #Color_Green
color(5) = #Color_Yellow : color(6) = #Color_Black
;}

flags.l = #PB_Window_BorderLess
title$ = "press escape to exit"
If Not OpenWindow(1,0,0,ScreenWidth,ScreenHeight,title$,flags) : End : EndIf
If Not OpenWindowedScreen(WindowID(1),0,0,ScreenWidth,ScreenHeight,0,0,0) : End : EndIf

 Repeat ;here is the endless animation loop
   StartDrawing(ScreenOutput())
   ;decide what to do based on the fuse status
   If fuse > 0 ;fuse is still burning so animate the embers
      fuse = fuse -1 ;countdown until next burst
      ;"a" is used to index each ember in array em(a,n)
      a = ode -1 ;start with the oldest ember

      Repeat ;this loop causes heavy cpu usage
         a = a + 1 : If a > max : a = 0 : EndIf ;wrap if needed
         
         ;erase the old version of ember "a"
         FrontColor(#Color_Black)
         LineXY(rm(a,0),rm(a,1),rm(a,2),rm(a,3))
         
         ;age the ember
         em(a,5) = em(a,5) - 1
         If em(a,5) = 0 ;ember burns out
            ;Erase the oldest ember; it doesn't have To be the one that
            ;just burned out; it will be erased eventually. No one will
            ;know the difference. :) Just paint it black.
           
            LineXY(rm(ode,0),rm(ode,1),rm(ode,2),rm(ode,3))
            ode = ode + 1 ;adjust the oldest ember pointer
            If ode > max : ode = 0 : EndIf ;wrap around if needed
         Else ;ember didn't burn out so draw a new version of ember "a"
            FrontColor(color(Int(em(a,4)))) ;set the pen's color
            LineXY(em(a,0),em(a,1),(em(a,0)-em(a,2)),(em(a,1)-em(a,3)))
           
            ;remember how it was drawn so we can erase later
            rm(a,0) = em(a,0) ;remember line x1 coord.
            rm(a,1) = em(a,1) ;remember line y1 coord.
            rm(a,2) = em(a,0)-em(a,2) ;remember line x2 coord.
            rm(a,3) = em(a,1)-em(a,3) ;remember line y2 coord.

            ;move the ember
            em(a,0) = em(a,0) + em(a,2) ;adjust ember x position
            em(a,1) = em(a,1) + em(a,3) ;adjust ember y position
            em(a,2) = em(a,2) * drag ;adjust x speed
            em(a,3) = em(a,3) * drag + gravity ;adjust y speed
         EndIf
      Until a = youngest
     
   Else ;fuse has reached the end so create a new burst
      ;set location for new burst
      x = devx - Random(devx * 2)
      y = Random(devy)

      embers = 50 + Random(100) ;set number of embers

      ;set dispersion force
       pow = embers / 6 ;larger number of embers get more pow

      cmix = Random(100) ;decide color scheme
      c1 = Random(5) : c2 = Random(5) ;choose two random colors
      shape = Random(100) ;chose the type of burst

      a = youngest
      For n = 1 To embers
         a = a + 1 : If a > max : a = 0 : EndIf ;wrap if needed

         em(a,5) = 10 + Random(60) ;set ember lifetime
         em(a,0) = x + midx ;set starting x coordinate for new ember
         em(a,1) = nomy - y ;set starting y coordinate for new ember
         alfa = tupi * RandFloat() ;2 * pi radians in a circle
         ;the initial velocities must be set to determine burst shape
         ;apply the magic formulas
         If shape > 15 ;sphere
            em(a,2) = Sin(alfa) * pow * Sin(RandFloat()*tupi) ;initial x velocity
            em(a,3) = Cos(alfa) * pow * Sin(RandFloat()*tupi) ;initial y velocity
         Else ;ellipse
            em(a,2) = Sin(alfa) * pow + Sin(RandFloat()*tupi) ;initial x velocity
            em(a,3) = Cos(alfa) * pow * 0.25 ;initial y velocity
         EndIf
         ;set color scheme
         If cmix > 75 ;use one color
            em(a,4) = c1
         ElseIf cmix < 65 ;use two colors
            If Random(1)
               em(a,4) = c1
            Else
               em(a,4) = c2
            EndIf
         Else ;use all colors
            em(a,4) = Random(5)
         EndIf
      Next n
      youngest = a ;remember which ember is youngest

      ;start fuse for next burst
      fuse = Random(15) + 25
   EndIf
   StopDrawing()
   FlipBuffers()
   Repeat
      event = WindowEvent()
   Until event = 0
   
   ;control the animation speed
   Delay(60)
   ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)


End

Procedure.f RandFloat()
   ;generate a random number ranging >0 and <1
   number.f = (Random(2147483645)+1) / (2147483647)
   ProcedureReturn number
EndProcedure


Top
 Profile  
 
 Post subject: Re: Fireworks
PostPosted: Wed May 25, 2011 8:02 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Apr 01, 2008 3:23 pm
Posts: 129
Very nice! :D
(and welcome back to the coding community)


Top
 Profile  
 
 Post subject: Re: Fireworks
PostPosted: Wed May 25, 2011 8:59 am 
Offline
New User
New User
User avatar

Joined: Tue May 24, 2011 11:58 pm
Posts: 9
Nice little program you've written up there, very nice!

_________________
PureBasic 4.51 User


Top
 Profile  
 
 Post subject: Re: Fireworks
PostPosted: Wed May 25, 2011 9:17 am 
Offline
Addict
Addict

Joined: Thu Nov 01, 2007 5:37 pm
Posts: 1564
Location: Germany
Nice looking result!

If you want to step a little further you could try to eliminate the arrays and put the particles into a linkedlist with structure.


Top
 Profile  
 
 Post subject: Re: Fireworks
PostPosted: Wed May 25, 2011 1:17 pm 
Offline
Addict
Addict
User avatar

Joined: Sat Feb 19, 2005 2:46 pm
Posts: 1334
Location: Pas-de-Calais, France
Welcome ! Very nice code, and realistic :)

_________________
The Shooting Crew ~> http://www.shootingcrew.com/
Bobble Puzzle, Purebreaker 3 ~> http://djes.free.fr


Top
 Profile  
 
 Post subject: Re: Fireworks
PostPosted: Wed May 25, 2011 1:55 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Mon Jun 06, 2005 2:35 pm
Posts: 577
Location: germany
Very nice. :D

But with SetFrameRate(30) and Delay(1), instead of Delay(60), it is much more smooth.

Kukulkan

_________________
There is not nothing that not might happen.


Top
 Profile  
 
 Post subject: Re: Fireworks
PostPosted: Wed May 25, 2011 6:25 pm 
Offline
Enthusiast
Enthusiast

Joined: Wed Aug 18, 2004 9:52 am
Posts: 370
Location: Penang, Malaysia
Nice Bang... I love it... Thanks.


Top
 Profile  
 
 Post subject: Re: Fireworks
PostPosted: Thu May 26, 2011 3:56 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Thu Mar 24, 2011 12:40 am
Posts: 155
Location: Iowa, USA
Thank you everyone for your replies to my posting.

Quote:
c4s wrote:
If you want to step a little further you could try to eliminate the arrays and put the particles into a linkedlist with structure.

That sounds like an excellent suggestion, unfortunately I don't know how to use linkedlists or structures yet.
I've learned a lot so far, but there is still a lot I don't know.
I presume that linkedlists and structures would make the coding easier and/or make it run faster.

Quote:
Kukulkan wrote:
But with SetFrameRate(30) and Delay(1), instead of Delay(60), it is much more smooth.

I tried your suggestion by placing SetFrameRate(30) on a line above Delay(1) and it seems the animation is way too fast.
I may not be using it correctly because it didn't seem to matter if I used a frame rate of 1 or 30, the speed was the same.
Only by increasing 'Delay()" could I slow the animation to a reasonable speed.

BP


Top
 Profile  
 
 Post subject: Re: Fireworks
PostPosted: Thu May 26, 2011 7:07 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Mon Jun 06, 2005 2:35 pm
Posts: 577
Location: germany
Using SetFrameRate(60) limits the speed to display a maximum of 60 frames per second. This is a good value (or 30), as most TFT's running this frequency. If your movement is to fast on 60 FPS, you better adopt your movement vectors (drag? gravity?) to fit to 60FPS. If someone uses a faster computer, he will get a maximum of 60 FPS, too. Upont his, the speed is the same for all (theoretically).

Kukulkan

_________________
There is not nothing that not might happen.


Top
 Profile  
 
 Post subject: Re: Fireworks
PostPosted: Thu Jun 02, 2011 11:12 pm 
Offline
Enthusiast
Enthusiast

Joined: Tue Oct 05, 2004 9:05 pm
Posts: 100
Location: Egypt
rulez!

_________________
Kultstudio


Top
 Profile  
 
 Post subject: Re: Fireworks
PostPosted: Sat May 05, 2012 11:55 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Thu Mar 24, 2011 12:40 am
Posts: 155
Location: Iowa, USA
It's been nearly a year since I made my first post here so I decided to revisit this one.
I have rewritten my original code using what I have learned since.

I discovered that the original code was somewhat 'twitchy' when run under Linux.
My new code seems to run fine on both Windows and Linux.
Probably good for Mac as well, but I can't test.

I'm not going to list all of the changes I made, I'll just post the code.

Code:
;Fireworks.pb by BasicallyPure
;05/24/2011
;updated 5/04/2012
;PureBasic 4.60, 4.61
;Linux users with PB 4.61, set the compiler options library subsystem to 'sdl'.

EnableExplicit

If Not InitSprite() Or Not InitKeyboard() : End : EndIf

ExamineDesktops()
Define ScreenWidth = DesktopWidth(0)
Define ScreenHeight = DesktopHeight(0)

;{ variable assignments
Define   max = 750 ; This sets the size of the ember array
Define   fuse = 0 ; countdown timer until next burst
Define   old = 0 ; index to oldest ember
Define   young = -1 ; index to youngest ember
Define   impulse = 20 ; determines average explosion force
Define.f drag = 0.97 ; 0 < drag < 1; smaller = more drag
Define.f gravity = 0.02
Define   burnTime = 150 ; determines average ember lifetime
Define   fuseTime = 25 ; determines average fuse time
Define.f tupi = 2*#PI, pow, alfa
Define   midx = ScreenWidth / 2 ; middle of screen
Define   devx = midx * 0.75 ; maximum x burst deviation from center
Define   nomy = ScreenHeight * 0.45 ; nominal y burst location
Define   devy = ScreenHeight * 0.25 ; maximum y deviation from nomy
Define   a, n, x, y, emberCount, cmix, c1, c2, shape

Structure emberStats
   x.f      ; x coordinate
   y.f      ; y coordinate
   vx.f     ; x velocity
   vy.f     ; y velocity
   color.i  ; ember color
   life.i   ; lifetime
EndStructure

Dim ember.emberStats(max)

Dim color(5) ; colors for embers
color(0) = $0000FF ; red
color(1) = $FFFF00 ; Cyan
color(2) = $FF00FF ; Pink
color(3) = $FFFFFF ; White
color(4) = $00FF00 ; Green
color(5) = $00FFFF ; Yellow
;}

If Not OpenScreen(ScreenWidth,ScreenHeight,32,"") : End : EndIf

Macro RndFloat
   ; produce a random float number (0 < number < 1)
   ((Random(2147483645)+1) / 2147483647)
EndMacro

SetFrameRate(30)

Repeat ; animation loop
   
   ;check the fuse status
   If fuse > 0 ;fuse is still burning so animate the embers
      fuse - 1 ;countdown until next burst
     
      StartDrawing(ScreenOutput())
      ;"a" is used to index each ember
      a = old - 1 ;start with the oldest ember
     
      Repeat ; update all of the embers
         a + 1 : If a > max : a = 0 : EndIf ; wrap if needed
         
         With ember(a)
            \life - 1 ; age the ember
           
            If \life = 0 ;ember burns out
               old + 1 ;adjust the oldest ember pointer
               If old > max : old = 0 : EndIf ; wrap around if needed
            Else ; ember didn't burn out so draw a new version
               FrontColor(color(\color)) ;set the pen's color
               LineXY(\x, \y, (\x - \vx), (\y - \vy))
               
               ;move the ember
               \x + \vx    ;adjust ember x position
               \y + \vy    ;adjust ember y position
               \vx * drag           ;adjust x speed
               \vy * drag + gravity ;adjust y speed
            EndIf
         EndWith
      Until a = young
     
      StopDrawing() : FlipBuffers() : ClearScreen(0)
     
   Else ; fuse has reached the end so create a new burst
      ; set location for new burst
      x = devx - Random(devx * 2)
      y = Random(devy)
     
      emberCount = 50 + Random(100) ; set number of embers
     
      ;set dispersion force
      pow = emberCount / impulse ; larger number of embers get more pow
     
      cmix = Random(100) ; decide color scheme
      c1 = Random(5) : c2 = Random(5) ; choose two random colors
      While c1 = c2 : c2 = Random(5) : Wend
      shape = Random(100) ; chose the type of burst
     
      a = young
      For n = 1 To emberCount
         a + 1 : If a > max : a = 0 : EndIf ; wrap if needed
         
         With ember(a)
            \life = 20 + Random(burnTime) ; set ember lifetime
            \x = x + midx ; set starting x coordinate for new ember
            \y = nomy - y ; set starting y coordinate for new ember
           
            alfa = tupi * RndFloat ; 2 * pi radians in a circle
           
            ; the initial velocities must be set to determine burst shape
            ; apply the magic formulas
            If shape > 15 ;sphere
               \vx = Sin(alfa) * pow * Sin(RndFloat * tupi) ; initial x velocity
               \vy = Cos(alfa) * pow * Sin(RndFloat * tupi) ; initial y velocity
            Else ; ellipse
               \vx = Sin(alfa) * pow + Sin(RndFloat * tupi) ; initial x velocity
               \vy = Cos(alfa) * pow * 0.25 ; initial y velocity
            EndIf
           
            ; apply color scheme
            If cmix > 75 ; use one color
               \color = c1
            ElseIf cmix < 65 ; use two colors
               If Random(1)
                  \color = c1
               Else
                  \color = c2
               EndIf
            Else ; use all colors
               \color = Random(5)
            EndIf
           
         EndWith
         
      Next n
      young = a ; remember which ember is youngest
     
      ; start fuse for next burst
      fuse = Random(fuseTime) + 25
   EndIf
   
   ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)


Last edited by BasicallyPure on Sun Jun 10, 2012 5:20 pm, edited 3 times in total.

Top
 Profile  
 
 Post subject: Re: Fireworks
PostPosted: Sun May 06, 2012 3:40 am 
Offline
Enthusiast
Enthusiast

Joined: Tue Oct 31, 2006 4:34 am
Posts: 427
Nice job BasicallyPure

I like this one much better than the first one, as it's much more realistic.
Thanks for sharing.


Top
 Profile  
 
 Post subject: Re: Fireworks
PostPosted: Sun May 06, 2012 9:35 am 
Offline
Addict
Addict
User avatar

Joined: Thu Apr 21, 2005 2:38 pm
Posts: 814
Location: Germany
BasicallyPure wrote:
Probably good for Mac as well, but I can't test.

Thank you, works nice on MacOS X 10.6.8 (Snow Leopard) :wink:


Top
 Profile  
 
 Post subject: Re: Fireworks
PostPosted: Thu May 24, 2012 10:14 am 
Offline
User
User
User avatar

Joined: Wed Apr 30, 2003 12:26 pm
Posts: 96
Location: France
Very nice !!
Faster than the 1st version.
WW

_________________
Beware of the man who has the solution before he understands the problem...


Top
 Profile  
 
 Post subject: Re: Fireworks
PostPosted: Thu May 24, 2012 6:42 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Thu Mar 24, 2011 12:40 am
Posts: 155
Location: Iowa, USA
Skipsy wrote:
Very nice !!
Faster than the 1st version.

Thanks,
After using PureBasic for a year then looking over the code I saw several
opportunities for improvement.

B.P.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: marroh and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye