Here is a new version of my Dungeon Generator. I have now used open and closed lists for the doors. The code can generate larger maps. Hundreds of rooms.
Code below :
This basically is how it works :
It creates one door in the open list.
It creates a room on the door and 3 new doors on the walls
the doors are added to the open list
it selects a random door and tries to create a new room there
if that fails then the door is removed from the open list. if it succeeds then it is removed from the open list and added to the closed list.
this continues until the number of rooms has been reached or the open list is empty (check for bounds to)
The door locations are in the closed list (x,y) and can be drawn to the map.
Import mojo
Const screenwidth:Int=640
Const screenheight:Int=480
Global tilewidth:Int=6
Global tileheight:Int=4
Global mapwidth:Int=100
Global mapheight:Int=100
Const isnothing:Int=0
Const iswall:Int=1
Const isfloor:Int=2
Const isdoor:Int=3
Const minroomw:Int=5
Const minroomh:Int=5
Const maxroomw:Int=10
Const maxroomh:Int=10
Global map:Int[mapwidth][]
Global rcount:Int=0
Class debug
Field x:Int
Field y:Int
Method New(_x:Int,_y:Int)
x=_x
y=_y
End Method
End Class
Class dooropenlist
Field x:Int
Field y:Int
Method New(_x:Int,_y:Int)
x=_x
y=_y
End Method
End Class
Class doorclosedlist
Field x:Int
Field y:Int
Method New(_x:Int,_y:Int)
x=_x
y=_y
End Method
End Class
Global dol:List<dooropenlist> = New List<dooropenlist>
Global dcl:List<doorclosedlist> = New List<doorclosedlist>
Global d:List<debug> = New List<debug>
Class MyGame Extends App
Method OnCreate()
SetUpdateRate(1)
Seed = Millisecs()
For Local i = 0 Until mapwidth
map[i] = New Int[mapheight]
Next
createmap(25,mapwidth/2,mapheight/2)
End Method
Method OnUpdate()
createmap(Rnd(10,125),mapwidth/2,mapheight/2)
End Method
Method OnRender()
Cls 0,0,0
SetColor 255,255,255
drawmap
End Method
End Class
Function createmap:Bool(numrooms:Int,sx:Int,sy:Int)
For Local y=0 Until mapheight
For Local x=0 Until mapwidth
map[x][y] = isnothing
Next
Next
d.Clear
dol.Clear
dcl.Clear
dol.AddLast(New dooropenlist(sx,sy))
Local roomcount:Int=0
Local tx:Int
Local ty:Int
While roomcount<numrooms And dol.IsEmpty() = False
Local founddoor:Bool=False
While founddoor=False
For Local i:=Eachin dol
If Rnd(100)<2
founddoor = True
tx = i.x
ty = i.y
Exit
End If
Next
Wend
If makeroomondoor(tx,ty) = True Then
roomcount+=1
removedoorfromopenlist(tx,ty)
dcl.AddLast(New doorclosedlist(tx,ty))
Else
removedoorfromopenlist(tx,ty)
End If
Wend
For Local i:=Eachin dcl
If i.x = sx And i.y = sy Then dcl.Remove i
Next
rcount = roomcount
End Function
Function makeroomondoor:Bool(x:Int,y:Int)
Local makeroom:Bool=False
Local cnt:Int=0
Local x1:Int
Local y1:Int
Local w1:Int
Local h1:Int
Local facing:String
If x+maxroomw > mapwidth Then Return False
If y+maxroomh > mapheight Then Return False
If x-maxroomw < 0 Then Return False
If y-maxroomh < 0 Then Return False
If map[x+1][y]=isnothing Then facing = "right"
If map[x][y-1]=isnothing Then facing = "up"
If map[x][y+1]=isnothing Then facing = "down"
If map[x-1][y]=isnothing Then facing = "left"
If facing="" Then Return False
While cnt<100
w1 = Rnd(minroomw,maxroomw)
h1 = Rnd(minroomh,maxroomh)
Select facing
Case "left"
x1=x-w1
y1=y-Rnd(h1/2)
Case "right"
x1=x+1
y1=y-Rnd(h1/2)
Case "up"
x1=x-Rnd(w1/2)
y1=y-h1
Case "down"
x1=x-Rnd(w1/2)
y1=y+1
End Select
If spaceisempty(x1,y1,w1,h1) = True Then
For Local y2=0 Until h1
For Local x2=0 Until w1
map[x2+x1][y2+y1] = isfloor
If y2 = 0 Or x2 = 0 Or y2 = h1-1 Or x2 = w1-1 Then map[x2+x1][y2+y1] = 1 ' wall
Next
Next
' shift map
Select facing
Case "left"
For Local y2=0 Until h1
For Local x2=w1 Until 0 Step -1
map[x2+x1][y2+y1] = map[x2+x1-1][y2+y1]
Next
Next
For Local y2=0 Until h1
map[x1][y2+y1] = isnothing
Next
'make doors
makedoors(x1,y1,w1,h1,True,False,True,True)
Case "right"
For Local y2=0 Until h1
For Local x2=0 Until w1
map[x2+x1-1][y2+y1] = map[x2+x1][y2+y1]
Next
Next
For Local y2=0 Until h1
map[x1+w1-1][y2+y1] = isnothing
Next
'make doors
makedoors(x1-1,y1,w1,h1,False,True,True,True)
Case "up"
For Local y2=h1 Until 0 Step -1
For Local x2=0 Until w1
map[x2+x1][y2+y1] = map[x2+x1][y2+y1-1]
Next
Next
For Local x2=0 Until w1
map[x1+x2][y1] = isnothing
Next
'make doors
makedoors(x1,y1+1,w1,h1,True,True,True,False)
Case "down"
For Local y2=0 Until h1
For Local x2=0 Until w1
map[x2+x1][y2+y1-1] = map[x2+x1][y2+y1]
Next
Next
For Local x2=0 Until w1
map[x1+x2][y1+h1-1] = isnothing
Next
'make doors
makedoors(x1-1,y1-1,w1+1,h1,True,True,False,True)
End Select
Return True
End If
cnt+=1
Wend
Return False
End Function
Function makedoors:Void(x:Int,y:Int,w:Int,h:Int,l:Bool,r:Bool,u:Bool,d:Bool)
Local dx:Int
Local dy:Int
If l=True Then 'left side
dx = x+1
dy = y+Rnd(h-4)+2
dol.AddLast(New dooropenlist(dx,dy))
End If
If r=True Then 'right side
dx = x+w-1
dy = y+Rnd(h-4)+2
dol.AddLast(New dooropenlist(dx,dy))
End If
If u=True Then 'up side
dx = x+Rnd(w-4)+2
dy = y
dol.AddLast(New dooropenlist(dx,dy))
End If
If d=True Then ' down side
dx = x+Rnd(w-4)+2
dy = y+h-1
dol.AddLast(New dooropenlist(dx,dy))
End If
End Function
Function spaceisempty:Bool(x:Int,y:Int,w:Int,h:Int)
For Local y1=0 Until h
For Local x1=0 Until w
If map[x1+x][y1+y] <> isnothing Then Return False
Next
Next
Return True
End Function
Function makeroom(x:Int,y:Int,w:Int,h:Int)
For Local y1=0 Until h
For Local x1=0 Until w
map[x1+x][y1+y] = 2 ' floor
If y1 = 0 Or x1 = 0 Or y1 = h-1 Or x1 = w-1 Then map[x1+x][y1+y] = 1 ' wall
Next
Next
End Function
Function drawmap:Bool()
For Local y=0 Until mapheight
For Local x=0 Until mapwidth
Select map[x][y]
Case isnothing ;
Case iswall ; SetColor 150,150,150 ' wall
Case isfloor ; SetColor 50,50,50 ' floor
Case isdoor ; SetColor 200,200,0 ' door
End Select
If map[x][y]<>isnothing Then DrawRect x*tilewidth,y*tileheight,tilewidth,tileheight
Next
Next
SetColor 255,255,0
For Local i:=Eachin dcl
DrawRect i.x*tilewidth,i.y*tileheight,tilewidth,tileheight
Next
SetColor 255,255,255
DrawText "Number of rooms :"+rcount,0,0
#rem
SetColor 255,0,0
For Local i:=Eachin d
DrawRect i.x*tilewidth,i.y*tileheight,tilewidth,tileheight
Next
#End
End Function
Function removedoorfromopenlist:Void(x:Int,y:Int)
For Local i:=Eachin dol
If i.x = x And i.y = y Then
dol.Remove i
d.AddLast(New debug(x,y))
Return
End If
Next
End Function
Function Main()
New MyGame()
End Function
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.