December 04, 2020, 10:41:31 AM

Author Topic: [bmx] TDungeon by impixi [ 1+ years ago ]  (Read 463 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bmx] TDungeon by impixi [ 1+ years ago ]
« on: June 29, 2017, 12:28:41 AM »
Title : TDungeon
Author : impixi
Posted : 1+ years ago

Description : Generate perfect mazes and imperfect dungeons

Code :
Code: BlitzMax
  1. See below for code...


Comments :


impixi(Posted 1+ years ago)

 Core class. Necessary for all the examples.TDungeon.bmx:
Code: [Select]

Rem

TDungeon
V0.1

December 2006


PURPOSE

A simple class for generating 'perfect' mazes and 'imperfect' dungeons


TEST SYSTEMS

Athlon 64 3200+, 2GB DDR400, ATI Radeon X800 GT 256MB GDDR3
Intel Centrino 1600, 512MB DDR2, ATI Radeon Mobility X700 128MB
Windows XP Pro SP2
BlitzMax V1.24


MINIMUM REQUIREMENTS

BlitzMax 1.24
Windows XP (Linux and MacOS untested)


VERSION CHANGES

0.1
 * Initial release


CONSTANTS

AREACLEAR_FULL
AREACLEAR_PERIMETER

AREATYPE_VOID
AREATYPE_PILLARS
AREATYPE_WALLED

ENTRY_INCLUDECORNERS
ENTRY_EXCLUDECORNERS


METHODS AND FUNCTIONS:

generate
checkNeighbour

createArea
clearCell
makeAreas

getWallGrid
getAreaGrid

NOTES:

Initially, all generated dungeons are 'perfect' mazes (that is, every cell in the maze is reachable by
every other cell).

To create a more interesting dungeon, 'areas' are added to the maze. An area is a space that may be
blank (void), or an empty 'room' with a number of 'entries'. Clever use of areas, alone or in combinations,
can offer interesting results. See the relevent method and the associated examples for more
information.  

End Rem


SuperStrict

Const AREACLEAR_FULL:Int = 0
Const AREACLEAR_PERIMETER:Int = 1
Const AREATYPE_VOID:Int = 0
Const AREATYPE_PILLARS:Int = 1
Const AREATYPE_WALLED: Int = 2
Const ENTRY_INCLUDECORNERS:Int = 0
Const ENTRY_EXCLUDECORNERS:Int = 1


Type TDungeon

Field SizeX:Int
Field SizeZ:Int
Field Dungeon:TDungeonCell[,]


Method generate(seed:Int = 0, szx:Int = 16, szz:Int = 16)
Rem
  Creates a 'perfect' maze.
  seed: random seed. Use Millisecs() to generate a different result every time.
  szx: number of grid columns. Minimum 16.
szz: number of grid rows. Minimum 16.
  End Rem

If szx < 1 Then SizeX = 16 Else SizeX = szx
If szz < 1 Then SizeZ = 16 Else SizeZ = szz

Dungeon = New TDungeonCell[SizeX, SizeZ]

For Local x:Int = 0 To SizeX - 1
For Local z:Int = 0 To SizeZ - 1
Dungeon[x, z] = New TDungeonCell
Dungeon[x, z].X = x
Dungeon[x, z].Z = z
Next
Next

SeedRnd seed

Local totalcells:Int = SizeX * SizeZ
Local cellstack:TDungeonCell[]
cellstack = cellstack[..cellstack.length + 1]
cellstack[cellstack.length - 1] = Dungeon[Rand(0, SizeX - 1), Rand(0, SizeZ - 1)]
Local currentcell:TDungeonCell = cellstack[cellstack.length - 1]
Local visitedcells:Int = 1

Local x:Int = currentcell.X
Local z:Int = currentcell.Z

While visitedcells < totalcells And (Not KeyHit(KEY_ESCAPE))

Local i:Int = -1
Local neighbors:TDungeonCell[4]
Local neighborsdir:Int[4]

If x > 0 Then checkNeighbour(Dungeon[x - 1, z], 2, i, neighbors, neighborsdir)
If x < (SizeX - 1) Then checkNeighbour(Dungeon[x + 1, z], 3, i, neighbors, neighborsdir)
If z > 0 Then checkNeighbour(Dungeon[x, z - 1], 0, i, neighbors, neighborsdir)
If z < (SizeZ - 1) Then checkNeighbour(Dungeon[x, z + 1], 1, i, neighbors, neighborsdir)

If (i > -1)
Local n:Int = Rand(0,i)

Select neighborsdir[n]
Case 0
currentcell.WallN = False
neighbors[n].WallS = False
Case 1
currentcell.WallS = False
neighbors[n].WallN = False
Case 2
currentcell.WallW = False
neighbors[n].WallE = False
Case 3
currentcell.WallE = False
neighbors[n].WallW = False
End Select

cellstack = cellstack[..cellstack.length + 1]
cellstack[cellstack.length - 1] = neighbors[n]
currentcell = cellstack[cellstack.length - 1]
x = currentcell.X
z = currentcell.Z

visitedcells :+ 1
Else
If cellstack.length > 0  
currentcell = cellstack[cellstack.length - 1]
x = currentcell.X
z = currentcell.Z
cellstack = cellstack[..cellstack.length - 1]
EndIf
EndIf

Wend

EndMethod


Function checkNeighbour(cell:TDungeonCell Var, ndir:Int, i:Int Var, neighbors:TDungeonCell[] Var, neighborsdir:Int[] Var)
Rem
Utility Function used by the generate method.
EndRem

If ((cell.WallN = True) And (cell.WallS = True) And (cell.WallE = True) And (cell.WallW = True))
i :+ 1
neighbors[i] = cell
neighborsdir[i] = ndir
EndIf

EndFunction


Method createArea(id:Byte = 0, posx:Int, posz:Int, sx:Int, sz:Int, cleartyp:Int = AREACLEAR_FULL, typ:Int = AREATYPE_VOID, typdata1:Int = 0, typdata2:Int = ENTRY_INCLUDECORNERS)
Rem
  Create an 'area' within the dungeon.
id: Area id number to assign to the area' cells. Minimum 0. Maximum 255.
  posx: Top left column of the area. > 0 and less than the dungeon's width.
posz: Top left row of the area. > 0 and less than the dungeon's height.
sx: width of the area. Minimum 3. Some area types require higher minimums for full effect.
sz: height of the area. Minumum 3. Some area types require higher minimums for full effect.
cleartyp: Clearing type. AREACLEAR_FULL - clear the entire area of walls.
AREACLEAR_PERIMETER - clear only the perimeter, preserving the inner contents.
typ: Type of area to create. AREATYPE_VOID - completely blank.
AREATYPE_PILLARS - pillars effect.
AREATYPE_WALLED - a walled room.
typdata1: if type is AREATYPE_WALLED then typdata1 = number of doors into room. Minimum 0.
typdata2: if type is AREATYPE_WALLED then typdata2 = corner door placement type. ENTRY_INCLUDECORNERS or ENTRY_EXCLUDECORNERS
  End Rem

If (posx < 0) Or (posx > (SizeX - 1)) Then Return
If (posz < 0) Or (posz > (SizeZ - 1)) Then Return
If (sx < 3) Or (sx >= SizeX) Then sx = 3
If (sz < 3) Or (sz >= SizeZ) Then sz = 3

'Tag relevent cells with the area id. Any existing id will be overwritten. ie a cell can only be
'classified as one room (though the visual effects will accrue)
For Local x:Int = posx + 1 To (posx + sx) - 2
For Local z:Int = posz + 1 To (posz + sz) - 2
If (x >= 0) And (x < SizeX) And (z >= 0) And (z < SizeZ) Then Dungeon[x, z].AreaID = id
Next
Next

If cleartyp = AREACLEAR_FULL

For Local x:Int = posx To (posx + sx) - 1
For Local z:Int = posz To (posz + sz) - 1
clearCell(x, z)
Next
Next

Else If cleartyp = AREACLEAR_PERIMETER

For Local x:Int = posx To (posx + sx) - 1
For Local z:Int = posz To (posz + 1)
clearCell(x, z)
Next
Next
For Local x:Int = posx To (posx + 1)
For Local z:Int = posz To (posz + sz) - 1
clearCell(x, z)
Next
Next
For Local x:Int = (posx + sx - 2) To (posx + sx) - 1
For Local z:Int = posz To (posz + sz) - 1
clearCell(x, z)
Next
Next
For Local x:Int = posx To (posx + sx) - 1
For Local z:Int = (posz + sz - 2) To (posz + sz) - 1
clearCell(x, z)
Next
Next

EndIf

Select typ

Case AREATYPE_VOID

Case AREATYPE_PILLARS

If sx >= 5 And sz >= 5 'Only possible if the width and height of the area is >= 5
For Local x:Int = (posx + 1) To (posx - 1 + sx) - 1 Step 2
For Local z:Int = (posz + 1) To (posz - 1 + sz) - 1 Step 2
If (x =< (SizeX - 1)) And (z =< (SizeZ - 1))
Local cell:TDungeonCell = Dungeon[x, z]
If (Not (x = 0)) Then cell.WallW = True
If (Not (z = 0)) Then cell.WallN = True
If (Not (x = (SizeX - 1))) Then cell.WallE = True
If (Not (z = (SizeZ - 1))) Then cell.WallS = True
EndIf
Next
Next
EndIf

Case AREATYPE_WALLED 'Walled room with entries.
'typdata1: number of doors
'typdata2 = 1: exclude corners

Local pdcells:TDungeonCell[] 'Potential room entries

'West and East
For Local z:Int = (posz + 1) To (posz + sz - 2)
If (z =< (SizeZ - 1))
Local x:Int = posx + 1
If x < SizeX
Local cell:TDungeonCell = Dungeon[x, z]
cell.WallW = True

pdcells = pdcells[..pdcells.length + 1]
pdcells[pdcells.length - 1] = cell

x = posx + sx - 2
If (x =< (SizeX - 1))
cell = Dungeon[x, z]
cell.WallE = True
pdcells = pdcells[..pdcells.length + 1]
pdcells[pdcells.length - 1] = cell
EndIf
EndIf
EndIf
Next

'North and South
For Local x:Int = (posx + 1) To (posx + sx - 2)
If (x =< (SizeX - 1))
Local z:Int = posz + 1
If z < SizeZ
Local cell:TDungeonCell = Dungeon[x, z]
cell.WallN = True

pdcells = pdcells[..pdcells.length + 1]
pdcells[pdcells.length - 1] = cell

z = posz + sz - 2
If (z =< (SizeZ - 1))
cell = Dungeon[x, z]
pdcells = pdcells[..pdcells.length + 1]
pdcells[pdcells.length - 1] = cell
cell.WallS = True
EndIf
EndIf
EndIf
Next

'If necessary, remove corners from potential entry list
If typdata2 = ENTRY_EXCLUDECORNERS

Local eol:Int = False
Local i:Int = 0

While (Not eol)

Local remove:Int = False

If pdcells

If (pdcells[i].X = (posx + 1) And pdcells[i].Z = (posz + 1))
remove = True
  Else
If (pdcells[i].X = (posx + sx - 2) And pdcells[i].Z = (posz + sz - 2))
remove = True
Else
If (pdcells[i].X = (posx + 1) And pdcells[i].Z = (posz + sz - 2))
remove = True
Else
If (pdcells[i].X = (posx + sx - 2) And pdcells[i].Z = (posz + 1))
remove = True
EndIf
EndIf
EndIf
EndIf

EndIf

If remove
pdcells[i] = pdcells[pdcells.length - 1]
pdcells = pdcells[..pdcells.length - 1]
Else
i :+ 1
EndIf



If i > pdcells.length - 1 Then eol = True

Wend

EndIf

'shuffle potential room entries
If (pdcells.length > 0)

For Local n:Int = 1 To 100
Local i1:Int = Rand(0, pdcells.length - 1)
Local i2:Int = Rand(0, pdcells.length - 1)
Local cell1:TDungeonCell = pdcells[i1]
Local cell2:TDungeonCell = pdcells[i2]
pdcells[i1] = cell2
pdcells[i2] = cell1
Next

'create entries
For Local n:Int = 0 To (typdata1 - 1)
If n < pdcells.length
clearCell(pdcells[n].X, pdcells[n].Z)
EndIf
Next

EndIf

EndSelect

EndMethod


Method clearCell(x:Int, z:Int)
Rem
Clear a specific cell of all walls, but presevere the dungeon's outermost edges if necessary.
x: cell column.
z: cell row.
End Rem

If (x =< (SizeX - 1)) And (z =< (SizeZ - 1))
Local cell:TDungeonCell = Dungeon[x, z]
If (Not (x = 0)) Then cell.WallW = False
If (Not (z = 0)) Then cell.WallN = False
If (Not (x = (SizeX - 1))) Then cell.WallE = False
If (Not (z = (SizeZ - 1))) Then cell.WallS = False
EndIf

EndMethod


Method makeAreas(qty:Int = 1, maxsizex:Int = 4, maxsizez:Int = 4)
Rem
Create a number of areas in the dungeon at random locations and of random sizes.
qty: Quantity of areas to create. Minimum 1.
maxsizex: Maximum possible area width. Minimum 4.
maxsizez: Maximum possible area height. Minimum 4.
EndRem

If qty <= 0 Then qty = 1
If maxsizex <= 3 Then maxsizex = 0.4 * SizeX
If maxsizez <= 3 Then maxsizez = 0.4 * SizeZ

For Local n:Int = 1 To qty
createArea(n, Rand(0, SizeX - maxsizex), Rand(0, SizeZ - maxsizez), Rand(3, maxsizex), Rand(3, maxsizez), Rand(0, 1), Rand(0, 2), Rand(1, 4), Rand(0, 1))
Next

EndMethod


Method getWallGrid:Byte[,]()
Rem
Create a grid representation of the dungeon's walls.
Most applications utilise such a data structure for dungeon processing.
Returns: 2d array of byte values. True = wall. False = no wall.
NOTE: The returned grid dimensions will be double the TDungeon sizes.
NOTE2:'Double' walls are ignored.
ie: North walls correspond to the South walls of the upper cell,
South walls correspond to the North walls of the lower cell,
East walls correspond to the West walls of the right cell,
West walls correspond to the East walls of the left cell.
EndRem

Local arr:Byte[SizeX * 2 + 1, SizeZ * 2 + 1]

For Local x:Int = 0 To SizeX - 1
Local ax:Int = x * 2 + 1
For Local z:Int = 0 To SizeZ - 1
Local az:Int = z * 2 + 1
If Dungeon[x, z].WallN = True
arr[ax, az - 1] = True
arr[ax - 1, az - 1] = True
arr[ax + 1, az - 1] = True
EndIf
If Dungeon[x, z].WallS = True
arr[ax, az + 1] = True
arr[ax - 1, az + 1] = True
arr[ax + 1, az + 1] = True
EndIf
If Dungeon[x, z].WallW = True
arr[ax - 1, az] = True
arr[ax - 1, az + 1] = True
arr[ax - 1, az - 1] = True
EndIf
If Dungeon[x, z].WallE = True
arr[ax + 1, az] = True
arr[ax + 1, az - 1] = True
arr[ax + 1, az + 1] = True
EndIf
Next
Next

Return arr

EndMethod


Method getAreaGrid:Byte[,]()
Rem
Create a grid representation of the dungeon's area ids.
Returns: 2d array of byte values. Values = ids.
NOTE: The returned grid dimensions will be double the TDungeon sizes.
EndRem
Local arr:Byte[SizeX * 2 + 1, SizeZ * 2 + 1]

For Local x:Int = 0 To SizeX - 1
Local ax:Int = x * 2 + 1
For Local z:Int = 0 To SizeZ - 1
Local az:Int = z * 2 + 1
If Dungeon[x, z].AreaID <> 0
arr[ax, az] = Dungeon[x, z].AreaID
arr[ax, az + 1] = Dungeon[x, z].AreaID
arr[ax , az - 1] = Dungeon[x, z].AreaID
arr[ax + 1, az] = Dungeon[x, z].AreaID
arr[ax + 1, az + 1] = Dungeon[x, z].AreaID
arr[ax + 1, az - 1] = Dungeon[x, z].AreaID
arr[ax - 1, az] = Dungeon[x, z].AreaID
arr[ax - 1, az + 1] = Dungeon[x, z].AreaID
arr[ax - 1, az - 1] = Dungeon[x, z].AreaID
EndIf
Next
Next

Return arr

EndMethod

EndType


Type TDungeonCell
Rem
Utility class used by TDungeon.
EndRem

Field WallN:Int = True
Field WallS:Int = True
Field WallE:Int = True
Field WallW:Int = True

Field X:Int
Field Z:Int

Field AreaID:Byte = 0

EndType

Maze Example 1test1.bmx:
Code: [Select]

Rem

TDungeon V0.1 Test #1 - Maze Example 1.


MINIMUM REQUIREMENTS

BlitzMax 1.24
Windows XP (Linux and MacOS untested, but should work)


DEPENDENCIES

TDungeon.bmx


NOTES

This example makes use of TDungeon's built-in TDungeonCell grid.

(*) - Indicates an essential step in creating and generating the maze.

A 'perfect' maze is one in which every cell can be reached by every other cell.
ie, there are NO closed sections inaccesable from other sections.

See TDungeon.bmx for function and method-specific documentation.

End Rem

' ----- INITIALISATION -----

SuperStrict

'(*) Import the TDungeon class file.
Import "TDungeon.bmx"

'Set up the graphics window.
AppTitle = "Maze Example 1"
Graphics 800, 600
SetBlend ALPHABLEND
SetAlpha 1.0
SetColor 0, 0, 0
SetClsColor 255, 255, 255

'Define some global variables to store the maze's dimensions.
Global Columns:Int = 32
Global Rows:Int = 32

'(*) Define and create an instance of the TDungeon class.
Global Maze:TDungeon = New TDungeon

'(*) Generate a 'perfect' maze measuring Columns x Rows dimensions.
Maze.generate MilliSecs(), Columns, Rows

' ----- MAIN LOOP -----

While Not KeyHit(KEY_ESCAPE)

Cls

'Generate a new maze if the left mouse button is clicked.
If MouseHit(1)
Maze.generate MilliSecs(), Columns, Rows
EndIf

'draw the maze onto the backbuffer.
drawMaze 16, 5, 5

DrawText "Left click to generate a new maze.", 5, (16 * (Rows + 1)) + 5

'Flip the backbuffer for screen display.
Flip 1

Delay 10

Wend

End

'----- FUNCTIONS -----

Function drawMaze(cell_size:Int = 8, col_offset:Int = 0, row_offset:Int = 0)

'Draw a simple representation of the maze.
'In this example, 'double' walls are ignored.
'ie: North walls correspond to the South walls of the upper cell,
' South walls correspond to the North walls of the lower cell,
' East walls correspond to the West walls of the right cell,
' West walls correspond to the East walls of the left cell.

'Iterate through every maze cell.
'sz and sx correspond to screen pixel coordinates.
For Local c:Int = 0 To Columns - 1
Local sx:Int = (c * cell_size) + col_offset

For Local r:Int = 0 To Rows - 1
Local sz:Int = (r * cell_size) + row_offset

'Draw an appropriate line for every wall:
'horizontal for north and south walls; vertical for east and west walls.
If Maze.Dungeon[c, r].WallN = True Then DrawLine sx, sz, sx + cell_size, sz
If Maze.Dungeon[c, r].WallS = True Then DrawLine sx, sz + cell_size, sx + cell_size, sz + cell_size
If Maze.Dungeon[c, r].WallW = True Then DrawLine sx, sz, sx, sz + cell_size
If Maze.Dungeon[c, r].WallE = True Then DrawLine sx + cell_size, sz, sx + cell_size, sz + cell_size
Next
Next

EndFunction

Maze Example 2test2.bmx:
Code: [Select]

Rem

TDungeon V0.1 Test #2 - Maze Example 2.


MINIMUM REQUIREMENTS

BlitzMax 1.24
Windows XP (Linux and MacOS untested, but should work)


DEPENDENCIES

TDungeon.bmx


NOTES

This example makes use of TDungeon's getWallGrid method.

(*) - Indicates an essential step in creating and generating the maze.

A 'perfect' maze is one in which every cell can be reached by every other cell.
ie, there are NO closed sections inaccesable from other sections.

See TDungeon.bmx for function and method-specific documentation.

End Rem

' ----- INITIALISATION -----

SuperStrict

'(*) Import the TDungeon class file.
Import "TDungeon.bmx"

'Set up the graphics window.
AppTitle = "Maze Example 2"
Graphics 800, 600
SetBlend ALPHABLEND
SetAlpha 1.0
SetColor 0, 0, 0
SetClsColor 255, 255, 255

'(*) Define a 2d BYTE array to store our walls.
'Note that no dimension sizes are specified.
Global WallGrid:Byte[,]

'Create some global variables to store the grid's dimensions.
'Again note that the sizes are not explicitely specified.
'They will be calculated later.
Global Columns:Int
Global Rows:Int

generateWallGrid

' ----- MAIN LOOP -----

While Not KeyHit(KEY_ESCAPE)

Cls

'Generate a new maze if the left mouse button is clicked.
If MouseHit(1)
generateWallGrid
EndIf

'draw the maze onto the backbuffer.
drawMaze 16, 5, 5

SetColor 0, 0, 0
DrawText "Left click to generate a new maze.", 5, (16 * (Rows + 1)) + 5

'Flip the backbuffer for screen display.
Flip 1

Delay 10

Wend

End

'----- FUNCTIONS -----

Function generateWallGrid()

'Define some local variables to store the maze's INITIAL dimensions.
Local initcols:Int = 16
Local initrows:Int = 16

'(*) Define and create an local instance of the TDungeon class.
Local maze:TDungeon = New TDungeon

'(*) Generate a 'perfect' maze measuring Columns x Rows dimensions.
maze.generate MilliSecs(), initcols, initrows

'(*) Get a True/False grid representation of the walls and assign it to our global MazeGrid variable
WallGrid = maze.getWallGrid()

'Set our global Columns and Rows based on the returned grids' dimensions:
'usually 2 x our initial dimensions, but it's best to calculate it this way just in case.
Local d:Int[] = WallGrid.Dimensions()
Columns = d[0]
Rows = d[1]

'Now that we have a grid representation of our maze we no longer need the TDungeon instance,
'so it can be deleted from memory. BlitzMax will automatically do this eventually
'but we'll force it to happen now:
maze = Null
GCCollect

EndFunction


Function drawMaze(cell_size:Int = 8, col_offset:Int = 0, row_offset:Int = 0)

'Draw a simple representation of the maze.

'Iterate through every maze cell.
'sz and sx correspond to screen pixel coordinates.
For Local c:Int = 0 To Columns - 1
Local sx:Int = (c * cell_size) + col_offset

For Local r:Int = 0 To Rows - 1
Local sz:Int = (r * cell_size) + row_offset

'Draw an appropriately colored rectangle for every cell:
'grey for walls; black for no wall.
If WallGrid[c, r] = True Then SetColor 100, 100, 100 Else SetColor 0, 0, 0
DrawRect sx, sz, cell_size, cell_size

Next
Next

EndFunction

Dungeon Example 1test3.bmx:
Code: [Select]

Rem

TDungeon V0.1 Test #3 - Dungeon Example 1.


MINIMUM REQUIREMENTS

BlitzMax 1.24
Windows XP (Linux and MacOS untested, but should work)


DEPENDENCIES

TDungeon.bmx


NOTES

This example makes use of TDungeon's built-in TDungeonCell grid.

In the context of the TDungeon class, dungeons are simply modifications to a 'perfect' maze.
'Areas' are created within the maze that similate open regions and rooms. Some interesting
results can be achieved by overlapping areas.

See test1.bmx for the basics of maze generation.

See TDungeon.bmx for function and method-specific documentation.

End Rem

' ----- INITIALISATION -----

SuperStrict

Import "TDungeon.bmx"

AppTitle = "Dungeon Example 1"
Graphics 800, 600
SetBlend ALPHABLEND
SetAlpha 1.0
SetColor 0, 0, 0
SetClsColor 255, 255, 255

Global AreaTog:Int = 0

Global Columns:Int = 32
Global Rows:Int = 32

Global MyDungeon:TDungeon = New TDungeon

generateMyDungeon

' ----- MAIN LOOP -----

While Not KeyHit(KEY_ESCAPE)

Cls

If MouseHit(1)
generateMyDungeon
EndIf

If MouseHit(2)
'Create a new walled area (ie room) of a random size in a random location.
'See the createArea method in the TDungeon class for more information.
MyDungeon.createArea(Rand(1, 255), Rand(1, Columns - 1), Rand(1, Rows - 1), Rand(4, 10), Rand(4, 10), Rand(0, 1), AREATYPE_WALLED, Rand(1, 4), ENTRY_EXCLUDECORNERS)
EndIf

If KeyHit(KEY_TAB) Then AreaTog :~ 1

drawDungeon 16, 5, 5

DrawText "Left click to generate a new dungeon.", 5, (16 * (Rows + 1)) + 5
DrawText "Right click to generate a new room.", 5, (16 * (Rows + 1)) + 20 + 5
DrawText "TAB toggles AreaID color.", 5, (16 * (Rows + 1)) + 40 + 5

Flip 1

Delay 10

Wend

End

'----- FUNCTIONS -----

Function generateMyDungeon()

MyDungeon.generate MilliSecs(), Columns, Rows

'Create a number of 'areas' in random locations and of random types and sizes.
'See the makeAreas and createArea methods in the TDungeon class for more information.
'Every cell has an AreaID (0 to 255), set whenever an area is created. This value can
'be used, for example, to determine 'enemy placement, environmental effects,
'door, floor and wall types, etc.
MyDungeon.makeAreas(12, 15, 15)

EndFunction

Function drawDungeon(cell_size:Int = 8, col_offset:Int = 0, row_offset:Int = 0)

'In this example, AreaID's <> 0 are denoted by green rectangles.
If AreaTog
SetColor 0, 196, 0  
For Local c:Int = 0 To Columns - 1
Local sx:Int = (c * cell_size) + col_offset
For Local r:Int = 0 To Rows - 1
Local sz:Int = (r * cell_size) + row_offset
  If MyDungeon.Dungeon[c, r].AreaID <> 0
DrawRect sx, sz, cell_size, cell_size
EndIf
Next
Next
EndIf

SetColor 0, 0, 0

For Local c:Int = 0 To Columns - 1
Local sx:Int = (c * cell_size) + col_offset

For Local r:Int = 0 To Rows - 1
Local sz:Int = (r * cell_size) + row_offset

If MyDungeon.Dungeon[c, r].WallN = True Then DrawLine sx, sz, sx + cell_size, sz
If MyDungeon.Dungeon[c, r].WallS = True Then DrawLine sx, sz + cell_size, sx + cell_size, sz + cell_size
If MyDungeon.Dungeon[c, r].WallW = True Then DrawLine sx, sz, sx, sz + cell_size
If MyDungeon.Dungeon[c, r].WallE = True Then DrawLine sx + cell_size, sz, sx + cell_size, sz + cell_size
Next
Next

EndFunction




impixi(Posted 1+ years ago)

 Edit: Removed dead links.


Booticus(Posted 1+ years ago)

 DUDE! this is totally taking me back! Dungeon Master, Ultima, right on! I appreciate the code and work you've done!


impixi(Posted 1+ years ago)

 .


puki(Posted 1+ years ago)

 BlitzMax?Sniffilisation.


impixi(Posted 1+ years ago)

 EDIT: Removed dead links.


SculptureOfSoul(Posted 1+ years ago)

 Awesome work. I might end up borrowing some ideas from this code to generate random dungeons for my MUD. Many thanks!


impixi(Posted 1+ years ago)

 EDIT: Removed dead links. [/i]

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal