Tuesday 11 December 2012

Grid on a .NET form

I needed to place a grid on the main form in a .NET application, the grid is a height field that I am generating for a random terrain generator.

When the form is loaded, the nMap class is instantiated with some definition stuff. The nMap class is where I process the grid of data representing the map cells. There is some processing stuff in the class that sets the RGB values for each of the cells.

Public Sub drawGrid(Optional ByVal minLines As Boolean = True, Optional ByVal majLines As Boolean = True)
        Dim cellRef As Long = 1024
        PictureBox1.Image = New Bitmap((CInt(nMap.width) * 10) + 20, (CInt(nMap.height) * 10) + 20)
        Using g As Graphics = Graphics.FromImage(PictureBox1.Image)
            Dim grayPen As New Drawing.Pen(Color.Gray)
            Dim blackPen As New Drawing.Pen(Color.Black)
            'cellcolour
            For i As Long = 0 To (nMap.width * nMap.height) - 1
                cellRef = i
                Dim nColour As New Color
                'Dim nAry As cellRGB = nMap.grid(i)
                'nColour = Color.FromArgb(nAry.R, nAry.G, nAry.B)
                Dim nAry() As String = nMap.grid(i).ToString.Split(":")
                nColour = Color.FromArgb(nAry(0), nAry(1), nAry(2))

                Dim nBrush = New SolidBrush(nColour)
                Dim X1, Y1 As Long
                X1 = 10 + ((cellRef - (Int(cellRef / nMap.width) * nMap.width)) * 10)
                Y1 = 10 + (Int(cellRef / nMap.width) * 10)
                g.FillRectangle(nBrush, New Rectangle(X1, Y1, 10, 10))
            Next

            Dim x As Integer
            Dim y As Integer

            Dim intSpacing As Integer = 10
            x = PictureBox1.Width

            'gridlines - minor gridlines
            If minLines Then
                For y = 10 To PictureBox1.Height - 10 Step intSpacing
                    g.DrawLine(grayPen, New Point(10, y), New Point(x - 10, y))
                Next
                y = PictureBox1.Height
                For x = 10 To PictureBox1.Width - 10 Step intSpacing
                    g.DrawLine(grayPen, New Point(x, 10), New Point(x, y - 10))
                Next
            End If
            'gridlines - major gridlines
            intSpacing = 100

            If majLines Then
                For y = 10 To PictureBox1.Height - 10 Step intSpacing
                    g.DrawLine(blackPen, New Point(10, y), New Point(x - 10, y))
                Next
                y = PictureBox1.Height
                For x = 10 To PictureBox1.Width - 10 Step intSpacing
                    g.DrawLine(blackPen, New Point(x, 10), New Point(x, y - 10))
                Next
            End If
        End Using
    End Sub

The Major and Minor gridlines can be turned on and off as suits. This happens in the redraw function.

Monday 10 December 2012

Grid Mapping – random terrain generation

I am working on writing a .NET application that will be used to generate a map. The idea is to create a bump map that can be used as a height field in a GIS application for fantasy worlds (for gaming).

What I want to be able to do, is to create a grid of X x Y proportions and then using the colour values of 000-000-000 through to 255-255-255 to set the altitude at any of the cells within the grid.

The grid starts out with all values at 125-125-125 and then through a process of randomly changing the altitude, I hope to end up with a height field that is “realistic”.

One of the challenges here, is that to change the altitude of a single cell, I need to know what is going on with it’s neighbours (North, North East, East, South East, South, South West and West), so that the change in altitude reflects the neighbouring cells altitude.

To work out the neighbouring cells, I made this spread-sheet in MS Excel:

Spreadsheet

The grid is simply a 10 x 10 grid of incrementing numbers. The cells have a bunch of conditional formats applied to them so that I can see what is being picked.

P1 is just a simple equality formula, where I pick the cell that I want as the reference cell. In the above example, it is F6.

ReferenceCell

I also want the grid to wrap on the X axis but not the Y axis, so that it is a cylinder, rather than a sphere. When the reference cell is < 10  the North values are –1 and when it is > 90, the South values are also –1.

North West

NorthWest

North

North

North East

NorthEast

East

East

South East

SouthEast

South

South

South West

SouthWest

West

West

So when I change the reference cell to, say B2 I get:

Spreadsheet_B2

and when I change it to K2, the grid looks like:

Spreadsheet_K2

So, it wraps the way that I planned. The formulae are probably not as elegant as they could be … but they will do for now.

When I tell my program to increase the altitude of a given cell, the formula will take the average of the surrounding cells and then add the increasing value to the reference cell.

I also want to have the program increase altitude in a radiating way. That is … poke the surface. If the increase in value is going to be, say, 10, then the reference cell has 10 added to it, while the surrounding 8 cells will have 5 added to them. If the program repeats this operation on random cells and with random altitude changes, then I should end up with a bumpy map. The same will happen for reductions in altitude: –10 for the reference cell and –5 for the surrounding cells.

So far, the tool generates the height field and does the initial random altitude change:

1st Grid

2nd Grid

3rd Grid

4th Grid

At the moment, everything averages down. It seems that the process is currently only reducing the cell values, rather than increasing them. I will have to work out why that is happening … it could be my calculation of the average values … not sure yet. Also, the GUI that I’ve built for this allows me to turn the major and minor grid lines off, so that it looks less like a shower recess.

Anyway, that’s where I am with the terrain generator for now.

Paypal Donations

Donations to help me to keep up the lunacy are greatly appreciated, but NOT mandatory.