Skip to navigation

Drawing the landscape: GetRowVisibility (Part 2 of 2)

Name: GetRowVisibility (Part 2 of 2) [Show more] Type: Subroutine Category: Drawing the landscape Summary: Calculate whether each tile corner in a tile row is obscured from the player by any intervening landscape
Context: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
\ In part 1 we set up xVector(Hi Lo Bot) with the vector \ from the player to the tile corner, split up into \ traceStepCounter steps, each of which is smaller than \ the size of a tile \ \ We can therefore trace the vector from the player to \ the tile corner by taking the player's coordinates and \ adding the vector: \ \ [ xVector(Hi Lo Bot) ] \ [ yVector(Hi Lo Bot) ] \ [ zVector(Hi Lo Bot) ] \ \ traceStepCounter times, knowing that together, these \ steps will stop over every tile between the player and \ the tile corner in the process (we may stop over some \ tiles more than once, but that's OK) \ \ I'll refer to this vector as the player's gaze, as it \ represents the line-of-sight from the player to the \ tile corner we are analysing \ \ So now we step along the player's gaze, checking on \ each step whether the gaze is passing over a tile that \ has a high enough altitude to block the player's view \ of the tile corner we are analysing .rvis6 LDX #2 \ We now work through all three axes in turn, so set an \ axis counter in X to iterate through 2, 1 and 0 (for \ the z-axis, y-axis and x-axis respectively) \ \ The comments in the following loop will concentrate on \ the x-axis to keep things simple CLC \ Clear the C flag so the initial addition at rvis8 will \ start properly BCC rvis8 \ Jump into the following loop at rvis8 so we start off \ that calculations with the z-axis and skip the bottom \ byte .rvis7 LDA xCoordBot,X \ For the y-axis calculation, we include the bottom byte ADC xVectorBot,X \ for more accuracy, so we calculate the following: STA xCoordBot,X \ \ xCoord(Hi Lo Bot) += xVector(Hi Lo Bot) .rvis8 \ This is where we join the loop to add the next step to \ the vector containing the current position along the \ player's gaze towards the tile corner we're analysing LDA xCoordLo,X \ Set xCoord(Hi Lo) += xVector(Hi Lo) ADC xVectorLo,X STA xCoordLo,X LDA xCoordHi,X ADC xVectorHi,X STA xCoordHi,X \ The calculation above adds the scaled vector from the \ player to the tile corner, which is in xVector, to the \ player's object coordinate, which is in xCoord \ \ So this calculation effectively follows the player's \ gaze towards the tile corner, adding one of the steps \ to the vector x-coordinate in xVector(Hi Lo) \ \ We repeat this for all three axes, calculating the \ x- and z-axes with 16-bit accuracy, and the y-axis \ with 24-bit accuracy (as y-coordinates are stored in \ this way) CLC \ Clear the C flag so the following additions work DEX \ Decrement the axis counter BEQ rvis8 \ If we are just about to calculate the x-axis, jump \ back to rvis8 to skip the bottom byte BPL rvis7 \ If we are about to calculate the y-axis, jump back to \ rvis7 to include the bottom byte \ We now work out whether this step has made the \ player's gaze pass over a tile that is high enough to \ block the player's view of the tile corner that we are \ heading for LDA zCoordHi \ Set the top byte of (S R) to the high byte of the STA S \ z-coordinate of our current step along gaze vector \ \ Because we added &60 to the starting z-coordinate in \ part 1, this will point to the &xx20 table of altitude \ data for the tile row over which the gaze is passing \ \ The GetTileAltitude routine populates the &xx20 table \ with the altitude of the highest tile corner for each \ tile, so (S R) now points to this data for the row \ over which we are passing LDY xCoordHi \ Set Y to the high byte of the x-coordinate of our \ current step along gaze vector, which is the tile \ x-coordinate of the tile that the gaze vector is \ currently passing over \ \ This means that (S R) + Y will contain the altitude \ of the highest tile corner for the tile that we are \ passing over LDA yCoordHi \ Set A to the high byte of the y-coordinate of our \ current step along gaze vector CMP (R),Y \ If yCoordHi < (S R) + Y then the altitude of the gaze BCC rvis9 \ vector is lower than the altitude of the highest point \ of the landscape on the tile over which we are \ passing, which means the gaze vector has hit the \ landscape before reaching the end \ \ So jump to rvis9 to record that this tile corner is \ not visible from the player's perspective, as it is \ hidden behind a higher part of the landscape between \ the player and the tile corner DEC traceStepCounter \ Otherwise decrement the step counter to keep moving \ along the vector BNE rvis6 \ If we haven't yet done all the steps, loop back to \ rvis6 to do the next step in the ray-trace \ If we get here then we have finished the ray-tracing \ process and we didn't bump into any tiles on the way, \ so the tile corner is not obscured by the landscape \ and is therefore deemed to be visible CLC \ Clear the C flag so we store %11111111 in the \ visibility table to indicate that this tile corner is \ visible BCC rvis10 \ Jump to rvis10 to store the result (this BCC is \ effectively a JMP as the C flag is always clear) .rvis9 SEC \ Set the C flag so we store %00000000 in the visibility \ table to indicate that this tile corner is not visible .rvis10 LDA xTileRow \ Set Y = drawingTableOffset + xTileRow ORA drawingTableOffset \ TAY \ The value of drawingTableOffset is either 0 or 32, so \ this creates an index in Y that we can use to store \ the result in either oddVisibility (when it is 0) or \ evenVisibility when it is 32) LDA #0 \ Set A = 0 - 0 - (1 - C) SBC #0 \ = C - 1 \ \ so this sets: \ \ * A = %00000000 if the C flag is set (not visible) \ \ * A = %11111111 if the C flag is clear (visible) STA oddVisibility,Y \ Store the result in either the oddVisibility or \ evenVisibility table, as determined by the value of \ drawingTableOffset DEC xTileRow \ Decrement xTileRow to move left along the tile row we \ are analysing BMI rvis11 \ If we have already processed the leftmost tile then \ jump to rvis11 to return from the subroutine JMP rvis1 \ Otherwise jump back to part 1 to analyse the next tile \ to the left .rvis11 RTS \ Return from the subroutine