Print Page | Close Window

Weather Tutorial *Gasp*

Printed From: Mirage Source
Category: Tutorials
Forum Name: Temporary Archive (Read Only)
Forum Discription: Temporary 3.0.3 archive tutorials, will be deleted when converted.
URL: http://ms.shannaracorp.com/backup-forums/forum_posts.asp?TID=212
Printed Date: 20 December 2006 at 5:53pm
Software Version: Web Wiz Forums 8.01 - http://www.webwizforums.com


Topic: Weather Tutorial *Gasp*
Posted By: Sync
Subject: Weather Tutorial *Gasp*
Date Posted: 11 February 2006 at 3:35pm
Yes kids, I decided to make a weather tutorial because I love you guys.

First off, this is only going to be the client-side part. Making the server send the client what the weather is, is very simple and I'm not going to go there. Hell, I may add it later if this tutorial is really popular. Also, unlike a simple, "Here's the code, copy/paste it.", I'm going to explain everything here. Lets get down to the brass tax, shall we?


1. Finding/Making the tiles.
You'll need to make or find rain tiles, snow tiles, or whatever other types of weather you want. The cool thing about this weather system is you can add as much weather effects as you'd like. I made these rain tiles in paint. Took 2 seconds, looks decent enough.
(NOTE: This is a JPEG format because these forums don't allow BMP posting. You're going to have to convert it or make your own!)

3 Tiles wide. Black is the "invisible" part. Make sure to name your .bmp Weather as well.


2. Initializing the Weather surface in DX.
If you didn't know, all graphics are stored on surfaces. Think of these as canvases that can stretch and shrink to any artwork. We need to make a canvas that will hold all our weather.

First, add the Surface variable. (The name of our "canvas".) This should be added to the list in the DirectX Module:
Public DD_WeatherSurf As DirectDrawSurface7


Now, lets initialize this puppy. This part won't make sense to you and it really doesn't matter. Just know that this basically prepares our surface and makes it useable. It also loads our Weather Tiles onto the canvas so they can be ready to use! Put the following code in the InitSurfaces sub under the other ones in the DirectX Module.

    ' Init weather ddsd type and load the bitmap
    DDSD_Weather.lFlags = DDSD_CAPS
    DDSD_Weather.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Or DDSCAPS_SYSTEMMEMORY
    Set DD_WeatherSurf = DD.CreateSurfaceFromFile(App.Path & "\Weather.bmp", DDSD_Weather)
    DD_WeatherSurf.SetColorKey DDCKEY_SRCBLT, key


Now what happens when we want the game to close. It's proper to "clear" our "canvases". In the DestroyDirectX sub in the DirectX Module, add this line:

    Set DD_WeatherSurf = Nothing


Before moving on, make sure you have these constants. If you didn't delete them, you still have them. I added thunder to the list. You can add whatever you want. I'm not sure where they originally start out, for I made a modConstants and stuck all the constants in there. Just hit Control & F and search for "WEATHER_".
' Weather constants
Public Const WEATHER_NONE = 0
Public Const WEATHER_RAINING = 1
Public Const WEATHER_SNOWING = 2
Public Const WEATHER_THUNDER = 3


Now the fun part... :D

3. Drawing the weather tiles onto the screen
In the game loop (In modGameLogic) is where we want to check if the weather isn't set to 0 (WEATHER_NONE). If it's not 0, do something about it! Since we want this weather to be drawn above the highest layer, we must put the "Check" after all other layers. I'm assuming your highest layer is Fringe. Finding the right spot to put it in is kind of tricky. I took the liberty of taking a screen shot to ease your efforts a bit. Paste this code in the right spot:
        ' Check for weather and draw if necessary
        If Map.Weather > 0 Then
             Call BltWeather(Map.Weather)
        End If




Now guess what folks, we're asking the computer to do something it can't find. BltWeather() Doesn't exist! Lets make it. You can basically throw this sub anywhere in the gameLogic module. I just stuck it at the bottom, no biggie. After I post the code, I'm going to break it down and explain it line by line:

Sub BltWeather(weatherType As Byte)

Static weatherFrame As Byte, lightCount As Byte
Dim rTemp As RECT, x As Integer, y As Integer, weatherTemp as Byte

If weathertype = WEATHER_THUNDER then
    weatherTemp = WEATHER_RAINING
Else
    weatherTemp = weatherType
End If

    With rTemp
        .top = (weatherType - 1) * PIC_Y
        .Bottom = .top + PIC_Y
        .Left = weatherFrame * PIC_X
        .Right = .Left + PIC_X
    End With
    
    ' Check if it's raining and draw it
    ' I decided to have rain with my thunder
    If weatherType = WEATHER_RAIN Or weatherType = WEATHER_THUNDER Then
        For y = 0 To MAX_MAPY
             For x = 0 To MAX_MAPX
                 Call DD_BackBuffer.BltFast(x * PIC_X, y * PIC_Y, DD_WeatherSurf, rTemp, DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY)
             Next x
        Next y
        If weatherFrame = 2 Then
             weatherFrame = 0
        Else
             weatherFrame = weatherFrame + 1
        End If
    End If
   
    ' If it's thunder, make the screen randomly flash blue
    If weatherType = WEATHER_THUNDER Then
        If Int((60 - 1 + 1) * Rnd) + 1 = 8 Then
             DD_BackBuffer.SetFillColor (16327202)
             Call DD_BackBuffer.DrawBox(0, 0, (MAX_MAPX + 1) * PIC_X, (MAX_MAPY + 1) * PIC_Y)
        End If
    End If

End Sub


Ok, ok, don't freak out. Let me explain.  :)

Sub BltWeather(weatherType As Byte)
That's simple enough. I'm telling the computer to create a sub called BltWeather. It requires a WeatherType to be passed. (ex: WEATHER_THUNDER)

Static weatherFrame As Byte
Dim rTemp As RECT, x As Integer, y As Integer

These are the variables I use to make this happen properly. First off, a Static variable is a normal variable except, unlike other variables, it keeps its Data even after you leave the sub. rTemp, x, and y, will be erased once this sub is through. rTemp is the Temporary Rectangle that I'm using. What it does is it tells the computer what "Chunk" I want of the Weather Surface drawn on the screen. (In this case, a tile.) X and Y tell the computer where on the screen to stick this "Chunk" (Tile).

    With rTemp
        .top = (weatherType - 1) * PIC_Y
        .Bottom = .top + PIC_Y
        .Left = weatherFrame * PIC_X
        .Right = .Left + PIC_X
    End With

If you've never seen a With statement, it's basically saying, "Computer, the next attributes I give you are attributes from this variable: rTemp." So .top is actually rTemp.top. Just a lil' shortcut I used, don't freak out if you don't understand. Now, we only need to find the top and left coordinates of where on the Weather.Bmp is the Chunk we want. Then we simply add 32 to find the bottom and right.

If it's raining for example (That makes weatherType = 1). Since it's the first row of tiles, 1 * 32 doesn't work because that skips the first row. So we need to shift all the rows back one. (weatherType - 1) * PIC_Y

Now for the frame part, it's simple. Whatever frame it's in, the beginning has to that number times PIC_X (32).

Kapeesh?

    ' Check if it's raining and draw it
    ' I decided to have rain with my thunder
    If weatherType = WEATHER_RAIN Or weatherType = WEATHER_THUNDER Then
        For y = 0 To MAX_MAPY
             For x = 0 To MAX_MAPX
                 Call DD_BackBuffer.BltFast(x * PIC_X, y * PIC_Y, DD_WeatherSurf, rTemp, DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY)
             Next x
        Next y
        If weatherFrame = 2 Then
             weatherFrame = 0
        Else
             weatherFrame = weatherFrame + 1
        End If
    End If


This is the rain-drawing part. I only have rain-drawing. If you want snow, add the same exact code but just change it to:
If weatherType = WEATHER_SNOW

Same thing for any other weather form you can think of.

Now it's saying, if it IS raining, lets scroll through every tile on the map, and paste our "Chunk" (Tile) that we got earlier onto the screen. Now we want to change the frame of the weather or else it would sit at the same frame and look dumb. If the frame hits 2 (The last frame), set it back to 0.

    ' If it's thunder, make the screen randomly flash blue
    If weatherType = WEATHER_THUNDER Then
        If Int((60 - 1 + 1) * Rnd) + 1 = 8 Then
             DD_BackBuffer.SetFillColor (16327202)
             Call DD_BackBuffer.DrawBox(0, 0, (MAX_MAPX + 1) * PIC_X, (MAX_MAPY + 1) * PIC_Y)
        End If
    End If

This is a little complicated bonus I added to add the effect of lightning on your screen. It first generates a random number. In this case 1-60. If the number is 8 (My lucky number), draw a fat blue square on the whole screen. Since the sub is called 16 times a second (16 FPS), eventually, the random number WILL be 8. To make the lightning flash less or more, modify the '60' in this line:
If Int((60 - 1 + 1) * Rnd) + 1 = 8 Then

(The higher the number, the less lightning there will be.)

That about wraps it up!  :D 

If you encounter any errors or have any problems, please post or contact me, I'd be more than happy to help. If you see any mistakes I made, let me know as well. For an unworking-tutorial isn't a good one at all.  :wink:

- Mr.Muffles

UPDATES AND BUG FIXES:
- In the modTypes, look for the type MapRec and add this if it isn't there:
    Weather As Byte

Now, either code your own server-side way of determining the weather OR just give it a test. I put something like this right before the game loop:
Map.Weather = WEATHER_RAINING ' Whatever type you want.




Print Page | Close Window

Bulletin Board Software by Web Wiz Forums version 8.01 - http://www.webwizforums.com
Copyright ©2001-2006 Web Wiz Guide - http://www.webwizguide.info