Hi Guys
I've been working a Rougelike game, and have recently completed some workable Line of Sight (LOS) code (see code below).
What it does it to draw a semicircle in the direction the player is facing, and then uses Brasenham's Algorhithm (function Line) to draw a line between the centre point (cx,cy in function DrawMap() ) and every point that comprises the semi circle.
The easiest way to get what I'm talking about it to copy and paste the code, and then get it running. In terms of the code, the important bit is the function Line(). I'm sure you guys can work out how the whole thing works :)
Left + Right = adjust direction
Up + Down = adjust vision distance
Mouse left = create cell
Mouse right = null cell
Pretty straightforwards, huh?
Well, if you start to adjust the vision distance you will start seeing black squares - i.e. places the line drawing function never goes through when drawing between the start point and semi-circle point. These are dead spaces that the player can't see.
My question is this: can the line drawing function be tweaked to ensure that all cells are "seen" or am I barking up the wrong tree?
If you can shed any light on this, I'd be extremely grateful.
I've been working a Rougelike game, and have recently completed some workable Line of Sight (LOS) code (see code below).
What it does it to draw a semicircle in the direction the player is facing, and then uses Brasenham's Algorhithm (function Line) to draw a line between the centre point (cx,cy in function DrawMap() ) and every point that comprises the semi circle.
The easiest way to get what I'm talking about it to copy and paste the code, and then get it running. In terms of the code, the important bit is the function Line(). I'm sure you guys can work out how the whole thing works :)
Left + Right = adjust direction
Up + Down = adjust vision distance
Mouse left = create cell
Mouse right = null cell
Pretty straightforwards, huh?
Well, if you start to adjust the vision distance you will start seeing black squares - i.e. places the line drawing function never goes through when drawing between the start point and semi-circle point. These are dead spaces that the player can't see.
My question is this: can the line drawing function be tweaked to ensure that all cells are "seen" or am I barking up the wrong tree?
If you can shed any light on this, I'd be extremely grateful.
SuperStrict Graphics 640,480,0,32 Local x:Int Local y:Int Global r:Int = 8 'default site distance Global w:Int = 8 'height and width of each cell Global s:Int = 1 'draw solid shape Global dir:Int 'direction faced Type cell Field x:Int Field y:Int End Type Const dungeon_x:Int = 50 Const dungeon_y:Int = 50 'Initialise the array Global dungeon:cell [dungeon_x,dungeon_y] For x = 0 To dungeon_x -1 For y = 0 To dungeon_y -1 dungeon [x,y] = New cell Next Next Const dir_north:Int = 0 Const dir_south:Int = 4 Const dir_east:Int = 2 Const dir_west:Int = 6 Const dir_northeast:Int = 1 Const dir_northwest:Int = 7 Const dir_southeast:Int = 3 Const dir_southwest:Int = 5 Global direction:String [8] direction[0] = "north" direction[1]="north east" direction[2]="east" direction[3]="south east" direction[4]="south" direction[5]="south west" direction[6]="west" direction[7]="north west" 'Main loop While Not KeyHit (key_escape) Cls SetColor 255,255,255 DrawText "Radius: " + r , 400,10 DrawText "Direction: " + direction[dir] , 400,40 drawmap keypress mouse Flip Wend Function checkCell:Int(x:Int, y:Int) If x < dungeon_x - 1 And y < dungeon_y -1 Then If dungeon [x,y] <> Null Then Return True End If End Function ' ' Draw the map and stuff ' ' Calculates each point of the semicircle, and then tries to draw a line ' between each point and the start point before moving onto the next point ' Function drawMap() Local x:Int Local y:Int Local xDiff:Int Local yDiff:Int Local cX:Int = 20 Local cY:Int = 20 For x = 0 To dungeon_x - 1 'draw grid SetColor 128,128,128 DrawLine x * w, 0, x * w, dungeon_y * w DrawLine 0,x * w, dungeon_x * w, x * w For y = 0 To dungeon_y - 1 'check the cell isn't null If dungeon [x,y] <> Null Then 'work out the difference between the start point 'and the semicircle point xDiff = x - Cx yDiff = y - Cx 'draw hollow circle If ((xDiff * xDiff) + (yDiff * yDiff)) < (r * r) And .. ((xDiff * xDiff) + (yDiff * yDiff)) > ((r*r) - (2*r)) Then SetColor 255,255,255 Select dir Case dir_north If (y <= cy) draw (cx,cy,x,y) End If Case dir_south If (y >= cy) draw (cx,cy,x,y) End If Case dir_east If (x >= cX) draw (cx,cy,x,y) End If Case dir_west If x <= cy draw (cx,cy,x,y) End If Case dir_northWest If x <=(cX + (r / 2) + 1) And y <=(cy + (r/2) + 1) draw (cx,cy,x,y) End If Case dir_northEast If x >=(cX - (r / 2) - 1) And y <=(cy + (r/2) + 1) draw (cx,cy,x,y) End If Case dir_southEast If x >= (cX - (r / 2) - 1) And y >= (cy - (r/2) - 1) draw (cx,cy,x,y) End If Case dir_southWest If x <= (cX + (r / 2) + 1) And y >= (cy - (r/2) - 1) draw (cx,cy,x,y) End If End Select End If End If Next Next End Function ' ' if flag s = 1 then draw a line between x1,y1 and x2,y2 ' else just draw x2,y2 - the circle's outline ' Function draw(x1:Int, y1:Int, x2:Int, y2:Int) If checkCell (x2, y2) = True Then If s = 1 Then line (x1,y1,x2,y2) Else DrawRect x1 * w, y1 * w, w -1 ,w -1 'start point DrawRect x2 * w, y2 * w, w -1 ,w -1 'semi-circle point End If End If End Function Function keypress() 'change direction If KeyHit (key_right) Then dir:+ 1 If dir > 7 Then dir = 0 End If 'change direction If KeyHit (key_left) Then dir:- 1 If dir < 0 Then dir = 7 End If 'increment vision distance If KeyHit (key_up) Then r:+1 End If 'decrement vision distance If KeyHit (key_down) Then r:-1 If r<0 Then r = 0 End If 'toggle line drawing If KeyHit (key_s) Then If s = True Then s = False Else s = True End If End If End Function ' ' Brasenham's alg: draw a line between x1, y1 and x2,y2 ' If a null cell is hit along the way bail out. ' ' Function Line(X1:Int,Y1:Int,X2:Int,Y2:Int) If s = True Then 'Draws a line of individual pixels from X1,Y1 to X2,Y2 at any angle Local Steep:Int=Abs(Y2-Y1) > Abs(X2-X1) 'Boolean If Steep Local Temp:Int=X1; X1=Y1; Y1=Temp 'Swap X1,Y1 Temp=X2; X2=Y2; Y2=Temp 'Swap X2,Y2 EndIf Local DeltaX:Int=Abs(X2-X1) 'X Difference Local DeltaY:Int=Abs(Y2-Y1) 'Y Difference Local Error:Int=0 'Overflow counter Local DeltaError:Int=DeltaY 'Counter adder Local X:Int=X1 'Start at X1,Y1 Local Y:Int=Y1 Local XStep:Int Local YStep:Int If X1<X2 Then XStep=1 Else XStep=-1 'Direction If Y1<Y2 Then YStep=1 Else YStep=-1 'Direction If Steep Then DrawRect y * w, x * w, w -1 ,w -1 Else DrawRect x * w, y * w, w -1 ,w -1 End If While X<>X2 X:+XStep 'Move in X Error:+DeltaError 'Add to counter If (Error Shl 1)> DeltaX 'Would it overflow? Y:+YStep 'Move in Y Error=Error-DeltaX 'Overflow/wrap the counter EndIf If Steep Then If checkcell (y,x) = True Then DrawRect y * w, x * w, w -1 ,w -1 Else Exit End If Else If checkcell (x,y) = True Then DrawRect x * w, y * w, w -1 ,w -1 Else Exit End If End If Wend End If End Function Function mouse() Local x:Int Local y:Int If MouseX() > 0 And .. MouseX() < (dungeon_x * w) And .. MouseY() > 0 And .. MouseY() < (dungeon_y * w) Then x = MouseX() / w y = MouseY() / w If MouseHit (1) Then If dungeon [x,y] = Null Then dungeon[x,y] = New cell End If If MouseHit (2) Then If dungeon [x,y] <> Null Then dungeon[x,y] = Null End If End If End Function