TGC Codebase Backup



Circular Line of Sight by Zwarteziel

7th Feb 2014 18:25
Summary

Circular Line of Sight: a program that lets a user navigate a map, while highlighting tiles that are in the player's Line of Sight (LOS).



Description

Circular Line of Sight: a program that generates a map from a file and lets the user navigate it, while highlighting tiles that are in the player's Line of Sight (LOS). The LOS is round (360dg.) but can be modified to check only a part of the circle. (For instance when one should one want to implement a method were a player can only look in the direction it is facing). The code needs a map-file (in \media\maps) which is included in the CodeBase as a .ZIP-file.



Code
                                    ` This code was downloaded from The Game Creators
                                    ` It is reproduced here with full permission
                                    ` http://www.thegamecreators.com
                                    
                                    //
// Round Line of Sight: a program that generates a map from a file and lets the user
// navigate it, while highlighting tiles that are in the player's Line of Sight (LOS).
// The LOS is round (360dg.), and based on an example from Roguebasin: bit.ly/1duW4dQ
// Needs a map-file (in \media\maps) which is included in the CodeBase as a .ZIP-file.
//
// Zerotown, AGK v1.821
//

`======================================================================================
` Set variables and assign values
`--------------------------------------------------------------------------------------
#constant KeyLeft   37
#constant KeyUp     38
#constant KeyRight  39
#constant KeyDown   40
#constant KeyEsc	27

// variables for the map
global MapLength        as integer  : MapLength =    64
global MapWidth         as integer  : MapWidth =     64

type MapUDT
    Char$       as string
    Visible     as integer
    Transparent as integer
endtype
dim Map[64, 64] as MapUDT

// variables for the sprites
global SprMap           as integer
global SprSize          as integer  : SprSize = 12
global SprPlayer        as integer
global SprPosX          as integer
global SprPosZ          as integer

// variables for debug information
global DebugInfo        as integer  : DebugInfo = 1

// variables for setting the screen
global ScreenAspect#    as float
global ScreenHeight#    as float
global ScreenMax#       as float
global ScreenMin#       as float
global ScreenWidth#     as float

// variables for minimap
global PlayerPosX       as integer
global PlayerPosZ       as integer
global MapSizeX#        as float    : MapSizeX# = MapWidth * SprSize
global MapSizeZ#        as float    : MapSizeZ# = MapLength * SprSize

// variables for the los-function
global GridX            as integer
global GridZ            as integer
global LOSRange         as integer  : LOSRange = 8
global SnapX#           as float
global SnapZ#           as float

// variables for the main loop
global GameState        as integer : GameState = 1


`======================================================================================
` Load data and create sprite
`--------------------------------------------------------------------------------------
LoadMap("maps/Dungeon02_64.map")

// create map-sprite
SprMap = CreateSprite(0)
setSpriteSize(SprMap, SprSize, SprSize)
setSpriteTransparency(SprMap, 0)
SetSpriteDepth(SprMap, 11)

// create player-sprite
SprPlayer = CreateSprite(0)
setSpriteSize(SprPlayer, SprSize, SprSize)
setSpriteColor(SprPlayer, 86, 117, 226, 255)
setSpriteTransparency(SprPlayer, 0)
SetSpriteDepth(SprPlayer, 10)


`======================================================================================
` Set the screen
`--------------------------------------------------------------------------------------
SetOrientationAllowed(0, 0, 1, 1)
SetVirtualResolution(1024, 768)
SetResolutionMode(0)
SetPrintSize(18)
SetClearColor(0, 0, 0)
SetScissor(0, 0, 0, 0)
SetSortTextures(1)
SetSyncRate(0, 0)

ScreenWidth# = GetVirtualWidth()
ScreenHeight# = GetVirtualHeight()

if ScreenWidth# > ScreenHeight#
	ScreenMin# = ScreenHeight#
	ScreenMax# = ScreenWidth#
else
	ScreenMin# = ScreenWidth#
	ScreenMax# = ScreenHeight#
endif
ScreenAspect# = ScreenMax# / ScreenMin#


`======================================================================================
` Set position of player
`--------------------------------------------------------------------------------------

// find a valid position for a 'player' which is used as a reference in this example
repeat
    PlayerPosX = Random(1, MapWidth)
    PlayerPosZ = Random(1, MapLength)
until Map[PlayerPosX, PlayerPosZ].Char$ = ":"


`======================================================================================
` Execute main program loop
`--------------------------------------------------------------------------------------

repeat

    // calculate player position on grid
    GetTilePos(PlayerPosX * SprSize, PlayerPosZ * SprSize, SprSize)

    // clear the current LOS
    ClearLOS(GridX, GridZ, LOSRange)

    // calculate the new LOS
    CalcLOS(GridX, GridZ, LOSRange)

    // show map
    ShowMiniMap(1, 1, MapWidth, MapLength)

    // position the player-sprite
    SetSpritePosition(SprPlayer, PlayerPosX * SprSize, PlayerPosZ * SprSize)

    // check for user input
    CheckInput()

    // display some debug-information
    if DebugInfo = 1
       ` print("FPS       : " + str(Screenfps()))
        print("Move with arrow keys")
        print("Position X/Y : " + str(GridX) + ", " + str(GridZ))
    endif

 Sync()

until GameState = 0

SetRawMouseVisible(1)
end


`======================================================================================
` Function to determine position on grid
`--------------------------------------------------------------------------------------
function GetTilePos(PosX#, PosZ#, Size)
    GridX = PosX# / Size
    GridZ = PosZ# / Size
endfunction


`======================================================================================
` Function to reset the LOS-values
`--------------------------------------------------------------------------------------
function ClearLOS(PosX, PosZ, Range)

    // reset all visible tiles within range and edge of range
    for z = PosZ - (Range + 1) to PosZ + (Range + 1)
        for x = PosX - (Range + 1) to PosX + (Range + 1)
            if z => 1 and z <= MapLength
                if x => 1 and x <= MapWidth
                    if Map[x, z].Visible = 1 then Map[x, z].Visible = 0
                endif
            endif
        next x
    next z

endfunction


`======================================================================================
` Function to calculate the line of sight for the player
`--------------------------------------------------------------------------------------
function CalcLOS(PosX, PosZ, Range)

    // check tiles within range of the player in an expanding circle
	for Angle# = 1 to 360 step 0.3  ` decrease stepsize to increase the accuracy with which tiles are checked. (results in slower calculation)
    	LOSPosX# = PosX + 0.5       ` convert positions of player to a float. Add 0.5 to place player in center of circle
    	LOSPosZ# = PosZ + 0.5
    	AngX# = Cos(Angle#)
    	AngZ# = Sin(Angle#)
    	Block = 0                   ` local variable to check if a position on the grid is blocked (1) or not (0)
    	Dist = 0                    ` local variable to check if distance set with LOSRange has been reached

		// check to see if something is blocking the LOS
    	while Block = 0
        	LOSPosX# = LOSPosX# + AngX#
        	LOSPosZ# = LOSPosZ# + AngZ#
        	Dist = Dist + 1

            // check if distance set by LOSRange has been reached
        	if Dist > Range then Block = 1

            // check if edges of the map have been reached
            if LOSPosX# < 1 then Block = 1
            if LOSPosZ# < 1 then Block = 1
        	if LOSPosX# > MapWidth then Block = 1
        	if LOSPosZ# > MapWidth then Block = 1

            // round float and convert position back to an integer
        	if Block = 0
            	TrcPosX = trunc(LOSPosX#)
            	TrcPosZ = trunc(LOSPosZ#)

                // check if an non-transparent tile is blocking our view
                if Map[TrcPosX, TrcPosZ].Transparent = 0
                    Block = 1

                    // ***
                    // *** UNREM the following code below when using the function in a game... it causes the blocking tile to be visible.
                    // *** The line is disabled here, because it visualizes the function better in this example.
                    // ***

                    ` if Map[TrcPosX, TrcPosZ].Visible = 0 then Map[TrcPosX, TrcPosZ].Visible = 1
            	endif

    			// set transparent tile to be visible if it isn't already
            	if Block = 0
                	if Map[TrcPosX, TrcPosZ].Visible = 0 then Map[TrcPosX, TrcPosZ].Visible = 1
            	endif
        	endif
    	endwhile

	next Angle#
endfunction


`======================================================================================
` Function to check user input
`--------------------------------------------------------------------------------------
function CheckInput()

    if GetRawKeyState(KeyUp) = 1
        PlayerPosZ = PlayerPosZ - 1
        if PlayerPosZ < 1 then PlayerPosZ = 1
    endif

    if GetRawKeyState(KeyDown) = 1
        PlayerPosZ = PlayerPosZ + 1
        if PlayerPosZ > MapLength then PlayerPosZ = MapLength
    endif

    if GetRawKeyState(KeyLeft) = 1
        PlayerPosX = PlayerPosX - 1
        if PlayerPosX < 1 then PlayerPosX = 1
    endif

    if GetRawKeyState(KeyRight) = 1
        PlayerPosX = PlayerPosX + 1
        if PlayerPosX > MapWidth then PlayerPosX = MapWidth
    endif

    if GetRawKeyState(KeyEsc) = 1 then GameState = 0

endfunction


`======================================================================================
` Function to load map-data from file
`--------------------------------------------------------------------------------------
function LoadMap(FileName$)
     if GetFileExists(FileName$) = 1
        FileId = OpenToRead(FileName$)

        for z = 1 to MapLength
            for x = 1 to MapWidth
            Char$ = chr(ReadByte(FileId))

            Map[x, z].Char$ = Char$
            Map[x, z].Visible = 0

            // determine whether tile can bee 'seen though' by player or not (e.g. a wall blocks the LOS)
            if Char$ = "D" then Map[x, z].Transparent = 1
            if Char$ = "O" then Map[x, z].Transparent = 0
            if Char$ = "U" then Map[x, z].Transparent = 0
            if Char$ = ":" then Map[x, z].Transparent = 1
            if Char$ = "." then Map[x, z].Transparent = 0
            if Char$ = "#" then Map[x, z].Transparent = 0
            if Char$ = "S" then Map[x, z].Transparent = 0

            next x
        next z
        CloseFile(FileId)
    else
        WriteDebugFile("Error in function [LoadMap]: file [FileName$] not found.")
    endif
endfunction


`======================================================================================
` Function to show the minimap [StartX, StartZ, EndX, EndZ]
`--------------------------------------------------------------------------------------
function ShowMiniMap(StartX, StartZ, EndX, EndZ)

    // display the minimap-sprites
    for z = StartZ to EndZ
        for x = StartX to EndX
            if z => 1 and z <= MapLength
                if x => 1 and x <= MapWidth

                    Char$ = Map[x, z].Char$

                    // set default sprite color
                    colR = 20
                    colG = 20
                    colB = 20
                    colA = 255

                    // set sprite color for door
                    if Char$ = "D" or Char$ = "O" or Char$ = "U"
                        colR = 132
                        colG = 128
                        colB = 112
                        colA = 255
                    endif

                    // set sprite color for floor
                    if Char$ = " " or Char$ = ":"
                        colR = 244
                        colG = 226
                        colB = 152
                        colA = 255
                    endif

                    // set sprite color for walls
                    if Char$ = "#" or Char$ = "S"
                        colR = 166
                        colG = 113
                        colB = 22
                        colA = 255
                    endif

                    // set sprite color for tiles in LOS
                    if Map[x, z].Visible = 1
                        colR = 255
                        colG = 255
                        colB = 255
                        colA = 100
                    endif

                    // draw sprite
                    SetSpritePosition(SprMap, (x + SprPosX ) * SprSize, (z + SprPosZ) * SprSize)
                    SetSpriteColor(SprMap, colR, colG, colB, colA)
                    DrawSprite(SprMap)

                endif
            endif
        next x
    next z
endfunction


`======================================================================================
` Function to write debug file
`--------------------------------------------------------------------------------------
function WriteDebugFile(Error$)
    FileId = OpenToWrite("debug.txt", 1)
    WriteLine(FileId, Error$)
     CloseFile(FileId)
endfunction