System Rain

Discussion in 'Systems and Snippets' started by Jesus4Lyf, Jun 30, 2009.

  1. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    Rain.

    They say, "when it rains, it pours". I've heard of rain in America and England recently, quite heavy rain, too, apparently. Today it rained here where I am. For those who don't know, we've had an epic drought for a long time, and well, it still hasn't broken. But I went for walk in the rain, and as I watched it gather in streams on the road and in the gutters, I smiled and thought to myself...

    Rain.

    :thup:

    I took a couple of "screenshots" for you all, too. I know some of you won't even bother to try this out. :)
    rain1.jpg
    rain2.jpg
    rain3.jpg
    rain4.jpg

    Code:
    JASS:
    library Rain initializer OnInit
        globals
            private constant real INITIAL_HEIGHT=1100.
            private constant real FALL_SPEED=20. // Divided by 32.
            private constant real RUN_SPEED=.4 // Divided by 32, dependant on smoothing, also.
            private constant real SMOOTHING=74.
            private constant integer LIFESPAN_TICKS=400 // Max raindrops, also.
            // ====
            private boolean Raining=true
            // ====
            private real MinX
            private real MaxX
            private real MinY
            private real MaxY
        endglobals
        public function Start takes nothing returns nothing
            set Raining=true
        endfunction
        public function Stop takes nothing returns nothing
            set Raining=false
        endfunction
        
        struct raindrop
            unit u
            real x=GetRandomReal(MinX,MaxX)
            real y=GetRandomReal(MinY,MaxY)
            real z=INITIAL_HEIGHT // also z for falling
            
            integer index // For the very end, removing from "Running"...
        endstruct
        
        private function RainHandler takes nothing returns nothing
            //====================================================
            // A different way to code...
            //====================================================
            globals//locals
                private integer i
                private raindrop Current
            endglobals
            
            //====================================================
            globals
                private raindrop array Remove
                private integer tick=0
                private integer later=LIFESPAN_TICKS
            endglobals
            
            // "later" must be always LIFESPAN_TICKS ahead of tick.
            set tick=tick+1
            if tick>8190 then
                set tick=1
            endif
            set later=later+1
            if later>8190 then
                set later=1
            endif
            
            //====================================================
            globals
                private raindrop array Running
                private integer RunningMax=0
            endglobals
            
            //====================================================
            globals
                private raindrop array Falling
                private integer FallingMax=0
            endglobals
            
            //====================================================
            // Timeout the old drops.
            //====================================================
            //  How to time out a vast number of objects with O(1)
            //  compelxity... :)
            set Current=Remove[tick]
            if Current!=0 then
                // When I first did this, this next line was missing.
                // Needless to say, if you understand the code, you
                // could guess it took me a little while to figure out.
                set Running[RunningMax].index=Current.index
                
                set Running[Current.index]=Running[RunningMax]
                set RunningMax=RunningMax-1
                
                call ShowUnit(Current.u,false)
                call UnitRemoveAbility(Current.u,'Aloc')
                call Current.destroy()
                
                set Remove[tick]=0
            endif
            
            //====================================================
            // Creation.
            if Raining then
                // Create a raindrop.
                set FallingMax=FallingMax+1
                set Current=raindrop.create()
                set Falling[FallingMax]=Current
                
                set Remove[later]=Current // So very efficient...
                
                call ShowUnit(Current.u,true)
                call SetUnitPosition(Current.u,Current.x,Current.y)
                call UnitAddAbility(Current.u,'Aloc')
                call SetUnitFlyHeight(Current.u,INITIAL_HEIGHT,0)
            endif
            
            //====================================================
            // Falling.
            set i=FallingMax
            loop
                exitwhen i==0
                set Current=Falling[i]
                set Current.z=Current.z-FALL_SPEED
                if Current.z<0. then
                    // ====
                    set Falling[i]=Falling[FallingMax]
                    set FallingMax=FallingMax-1
                    
                    call SetUnitFlyHeight(Current.u,0,0)
                    
                    set RunningMax=RunningMax+1
                    set Running[RunningMax]=Current
                    
                    set Current.index=RunningMax // To remove from running.
                    // ====
                else
                    call SetUnitFlyHeight(Current.u,Current.z,0)
                endif
                
                set i=i-1
            endloop
            
            //====================================================
            // Running.
            globals
                private location l=Location(0,0)
                private real rainx // JassHelper error if renamed to x.
                private real rainy // JassHelper error if renamed to y.
                private real thisz
            endglobals
            
            set i=RunningMax
            loop
                exitwhen i==0
                set Current=Running[i]
                
                // Update velocities.
                set rainx=Current.x
                set rainy=Current.y
                call MoveLocation(l,rainx,rainy)
                set thisz=GetLocationZ(l)
                call MoveLocation(l,rainx+SMOOTHING,rainy)
                set Current.x=rainx+(thisz-GetLocationZ(l))*RUN_SPEED
                call MoveLocation(l,rainx,rainy+SMOOTHING)
                set Current.y=rainy+(thisz-GetLocationZ(l))*RUN_SPEED
                
                // Move raindrop.
                call SetUnitX(Current.u,Current.x)
                call SetUnitY(Current.u,Current.y)
                
                set i=i-1
            endloop
        endfunction
        
        private function OnInit takes nothing returns nothing
            local raindrop r=LIFESPAN_TICKS
            set MinX=GetCameraBoundMinX()
            set MaxX=GetCameraBoundMaxX()
            set MinY=GetCameraBoundMinY()
            set MaxY=GetCameraBoundMaxY()
            call TimerStart(CreateTimer(),0.03125,true,function RainHandler)
            loop
                exitwhen r==0
                set r.u=CreateUnit(Player(15),'rain',MinY,MinX,0)
                call ShowUnit(r.u,false)
                set r=r-1
            endloop
        endfunction
    endlibrary
    In regards to real use... You probably want Bound Sentinel or a carefully created terrain, copy the dummy "Rain Drop" unit in the map as well as the code, and be warned that any terrain effects at runtime like shockwave and thunderclap will very likely desynch people.

    Oh, and I enjoyed my walk very much. :)

    PS.
    If you think you have a good computer, see how high you can bump up "LIFESPAN_TICKS" and have the map run for at least a minute (if it can last that long, it should last forever probably). Tell us how high you got and what your fps was! (Use /fps in chat to find this out.) This can be some kinda test as to how well WC3 runs on your computer. And for anyone who previously thought moving 200 units around 32 times a second based on terrain was laggy... think twice, hey? :)

    I've very tightly optimised this. =]
     

    Attached Files:

    • Rain.w3x
      File size:
      47.6 KB
      Views:
      353
    • Like Like x 3
  2. wellwish3r

    wellwish3r wishes wells.

    Ratings:
    +52 / 0 / -0
    wow now this is something original :thup:

    i like, however i think it would only be useful in cinematics?
     
  3. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    I adjusted to 500, fps drops to 45.

    I think dummies can be recycled..

    Original :
    JASS:
    set Current.u=CreateUnit(Player(15),'rain',Current.x,Current.y,0)

    JASS:
    call RemoveUnit(Current.u)


    Recycle :
    JASS:
    if Current.u == null then
        set Current.u=CreateUnit(Player(15),'rain',Current.x,Current.y,0)
    else
        call ShowUnit(Current.u,true)
        call SetUnitPosition(Current.u,Current.x,Current.y)
    endif

    JASS:
        call ShowUnit(Current.u,false)
     
  4. wellwish3r

    wellwish3r wishes wells.

    Ratings:
    +52 / 0 / -0
    I tried 2000, and it kinda died after 40seconds or so
     
  5. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    Pretty much. But I couldn't like... leave it in my maps folder and go "well I reckon that was epic, but no one shall ever know of it". I'm sure someone may find some use for it, even if its only to sit in their room occasionally and stare at the drops running down the streams... :thup: XD

    And this would benefit... what? (I don't believe this would bring an efficiency increase, but I DO know that it would leave a few hundred dummy units sitting in the background if the Rain_Stop and Rain_Start functions were used. ;))

    Well. I've gotten the same amount of +rep for this and AIDS so far... o.o -.-

    Edit: More posts before I posted! :O
    2000 takes 62 seconds to reach and stabilise. Try 1000. Should even work on your computer.

    By the way, at 200 my computer runs on about 25 fps... lol :p

    I'd love to see a screenshot of 1000... <3
     
  6. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    And this would benefit... what? (I don't believe this would bring an efficiency increase, but I DO know that it would leave a few hundred dummy units sitting in the background if the Rain_Stop and Rain_Start functions were used. )

    In this case... You had to remove all dummies... T.T

    Offtopic:)P) : Huh? Can the "pro" projectile system greatly reduce the length of code?

    2000?!, Warcraft die after 35s with the value. FPS drops to 1.4 only. lol.

    1000 raindrops :
    [​IMG]
     
  7. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    =/ You mean Gwypaas's? This probably wouldn't even run 200 with his.

    Turns out it runs 400 smoothly on mine. There ya go. The screenies are only with 200. :)

    Hmm. I could put recycling in. But I don't know that CreateUnit is really that much slower than ShowUnit and SetUnitPos. But I suppose it is probably worthwhile.

    Disappointingly enough, the system's complexity seems to... unpredictably falter after a certain amount of time. Maybe recycling could fix this. Hmm. Unsure what that is. :)

    >2000?!, Warcraft die after 35s with the value. FPS drops to 1.4 only. lol.
    That means it only reached about 1100, and hasn't destroyed a single unit. :p
     
  8. Tyrande_ma3x

    Tyrande_ma3x .

    Ratings:
    +91 / 0 / -0
    This is really awesome but I think it's a little laggy (from stable 64 fps to 57-61) but it's quite normal for such a big amount of moved units. I like it. :thup:
     
  9. wellwish3r

    wellwish3r wishes wells.

    Ratings:
    +52 / 0 / -0
    Well here is one at 1000 (ran perfectly fine):

    [​IMG]

    On a side note, i have to say that this was taken at all wc3 settings at mac with a resolution of 1920x1200, so if i went a little lower, i could maybe get to 2000 :p
     
  10. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    Hawt.

    I updated the code to preload all units, and then recycle them. It screwed with locust so I had to fix that too. :)

    Runs epic smooth now. By the way, not sure that having more than 1000 units serves a point. Does it look any better to you changing from like... 600 to 1000? XD lol
     
  11. wellwish3r

    wellwish3r wishes wells.

    Ratings:
    +52 / 0 / -0
    to be honest, i saw now real different, except for maybe there bing more dummies running down the hills^^
     
  12. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    200 works good for me. No fps drops. 200 is sufficient and optimum, but not for beginner class graphic cards..

    The new version.... My fps increased by 5 compared with old version.
     
  13. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    >maybe there bing more dummies running down the hills^^
    Shouldn't be. It only changes the lifespan! :p

    I agree that 200 is fine. :)

    Cooool. :D

    I might make a chill-out-at-2-am type map with this and some first person stuff on it. Hmm. Maybe, maybe... =]
     
  14. kingkingyyk3

    kingkingyyk3 Visitor (Welcome to the Jungle, Baby!)

    Ratings:
    +216 / 0 / -0
    How about simulate other weather effects, like snow?
     
  15. wellwish3r

    wellwish3r wishes wells.

    Ratings:
    +52 / 0 / -0
    Well i think this is a lot more awesome xD

    [​IMG]

    Btw: I can't see the updated version attached anywhere?

    EDIT: Lol no its there >.>
     
  16. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    When I walk outside one day and see snow falling and gathering on fresh ground, maybe I'll be inspired to do that. :thup:

    But it doesn't snow here.

    And I don't usually speak in full caps but OMG THAT LOOKS AWESOME LOL.

    PS. It didn't attach for some reason, but I did re-attach it. :p lol

    Feel free to post your map for that fire one just for kicks, if you like... XD :)

    Edit: Actually, I might do snow one day. But really it's just a case of removing the "running" in this and changing the projectile to frostwyrm breath... o.o
     
  17. wellwish3r

    wellwish3r wishes wells.

    Ratings:
    +52 / 0 / -0
    sure, but in the end it was just a replace tiles+trees and some random fire thrown in :p
     

    Attached Files:

    • Like Like x 1
  18. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    Psh, I know that! Still cool though...

    Updated the first post by removing my debug messages, lol. :thup:

    Edit: Did someone say... snow? XD
    *Shrugs* lol kinda works. :)
     

    Attached Files:

  19. wellwish3r

    wellwish3r wishes wells.

    Ratings:
    +52 / 0 / -0
    you know i just had an idea, how about making the raindrops get continuously smaller as they run down the terrain? Sort of like what real streams do when running a hill. Just an idea tho^^

    EDIT: One comment for the snow: Make the dummies smaller, right now it looks like friggn comets rain from the sky (and then probably spawn them more frequently, since you have a lot less dummies on the map compared to rain.)
    EDIT: Snow usually doesn't fall down straight, it sort of moves about randomly (like a falling paper)
     
  20. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    Hmm. Streams actually get -larger- as they go, usually, I think... XD

    In regards to snow... meh. It was just for kicks. :p
     

Share This Page