.GetTileViewAngles STY xTile \ Store the tile column in xTile, so we can analyse the \ tile at (xTile, zTile) STY yStoreTileView \ Store Y in yStoreTileView so it can be preserved \ across calls to the routine TYA \ Set drawingTableIndex = Y + drawingTableOffset ORA drawingTableOffset \ STA drawingTableIndex \ So drawingTableIndex is the index into the drawing \ tables for the tile we are analysing LDA #0 \ Set tileIsOnScreen = 0, so the default is that the STA tileIsOnScreen \ tile is not on-screen (we change this in part 3 if it \ is on-screen) LDX viewingObject \ Set X to the number of the object that is viewing the \ landscape \ We start by calculating the difference (the delta) in \ the x-axis between the viewer and the tile we are \ analysing LDA #128 \ Set the low byte of xDelta(Hi Lo) to 128 STA xDeltaLo CLC \ Set the high byte of xDelta(Hi Lo) to the LDA xTile \ following: SBC xTileViewer \ SEC \ xTile - xTileViewer - 1 - xTitleOffset SBC xTitleOffset \ STA xDeltaHi \ Note that xTitleOffset is zero during gameplay, and is \ only non-zero when we are drawing large 3D text on the \ title screen, so let's ignore it for now to keep \ things simple \ \ Setting the low byte to 128 effectively adds 0.5 to \ the result, so we get this: \ \ xDelta(Hi Lo) = xTile - xTileViewer - 0.5 \ \ So this is the delta along the x-axis between the \ viewer and the tile that we are analysing BPL tang1 \ If the result is positive then jump to tang1 to skip \ the following LDA #0 \ Negate the result to make it positive, so we now have: SEC \ SBC xDeltaLo \ (A xDeltaLo) = |xTile - xTileViewer - 0.5| STA xDeltaLo LDA #0 SBC xDeltaHi .tang1 STA xDeltaAbsoluteHi \ Set xDeltaAbsoluteHi = |xDeltaHi| \ \ So we now have the absolute z-axis length in: \ \ (xDeltaAbsoluteHi xDeltaLo) \ \ and the original high byte of the signed x-axis length \ is still in xDeltaHi \ We now do the same thing but for the z-axis, so that \ zDelta contains the difference (the delta) in the \ z-axis between the viewer and the tile we are \ analysing LDA #128 \ Set the low byte of zDelta(Hi Lo) to 128 STA zDeltaLo CLC \ Set the high byte of zDelta(Hi Lo) to the LDA zTile \ following: SBC zTileViewer \ STA zDeltaHi \ zTile - zTileViewer - 1 \ \ Setting the low byte to 128 effectively adds 0.5 to \ the result, so we get this: \ \ zDelta(Hi Lo) = zTile - zTileViewer - 0.5 \ \ So this is the delta along the z-axis between the \ viewer and the tile that we are analysing BPL tang2 \ If the result is positive then jump to tang2 to skip \ the following LDA #0 \ Negate the result to make it positive, so we now have: SEC \ SBC zDeltaLo \ (A zDeltaLo) = |zTile - zTileViewer - 0.5| STA zDeltaLo LDA #0 SBC zDeltaHi .tang2 STA zDeltaAbsoluteHi \ Set zDeltaAbsoluteHi = |zDeltaHi| \ \ So we now have the absolute z-axis length in: \ \ (zDeltaAbsoluteHi zDeltaLo) \ \ and the original high byte of the signed z-axis length \ is still in zDeltaHi \ We now have both deltas, so we now can calculate the \ angle of the hypotenuse of the triangle formed by \ these axes, which is the projection of the 3D vector \ from the viewer to the tile down onto the ground plane \ (so imagine a light shining down from above, casting \ the vector's shadow onto the y = 0 plane, and that's \ the hypotenuse) JSR GetHypotenuseAngle \ Calculate the angle of the hypotenuse in the triangle \ with the following non-hypotenuse sides: \ \ * xDelta(Hi Lo) \ \ * zDelta(Hi Lo) \ \ and return the angle in angle(Hi Lo), the tangent in \ angleTangent, the length of the longer side in \ a(Hi Lo) and the length of the shorter side in \ b(Hi Lo) \ The angle of the hypotenuse is the yaw angle of the \ 3D vector from the viewer to the tile corner we are \ analysing, so store it in the table at \ drawViewYaw(Hi Lo) \ \ We also subtract the following: \ \ * screenLeftYawHi from the high byte so the result \ is the relative yaw angle from the left edge of \ the screen, so the result is effectively a screen \ x-coordinate where zero is the left screen edge \ \ * yawAdjustmentLo from the low byte so if we are \ drawing an object for updating, we include the \ correct yaw offset to enable the object to be \ drawn flush with the left edge of the screen \ buffer (see the DrawUpdatedObject routine) LDY drawingTableIndex \ Set Y to the drawing table index for this tile LDA angleLo \ Set drawViewYaw(Hi Lo) for this tile to: SEC \ SBC yawAdjustmentLo \ angle(Hi Lo) - (screenLeftYawHi 0) STA drawViewYawLo,Y \ - (0 yawAdjustmentLo) \ \ starting with the low bytes LDA angleHi \ And then the high bytes SBC screenLeftYawHi STA drawViewYawHi,Y JSR GetHypotenuse \ Calculate the length of the hypotenuse in the triangle \ with side lengths of a(Hi Lo) and b(Hi Lo) and angle \ angleTangent, which are still set from the call to \ GetHypotenuseAngle above to the values for the 3D \ vector from the viewer to the tile corner we are \ analysing \ \ The hypotenuse length is returned in hypotenuse(Hi Lo) \ so we can use it to calculate the pitch angle of the \ viewer-to-tile vector in part 3 \ Fall through into part 2 to start the pitch angle \ calculationsName: GetTileViewAngles (Part 1 of 4) [Show more] Type: Subroutine Category: Drawing the landscape Summary: Calculate the pitch and yaw angles for a tile corner, relative to a viewer object (e.g. the player), and whether it is on-screenContext: See this subroutine in context in the source code References: This subroutine is called as follows: * DrawLandscapeView (Part 2 of 3) calls GetTileViewAngles * DrawLandscapeView (Part 3 of 3) calls GetTileViewAngles * GetTileEdgeToLeft calls GetTileViewAngles * GetTileViewEdges calls GetTileViewAngles
Arguments: Y The tile column of the tile we are analysing, from the perspective of the viewer zTile The tile row of the tile we are analysing, from the perspective of the viewer drawingTableOffset Defines where we store the results of the analysis in the tileViewData, tileViewYaw and tileViewPitch drawing data tables; each table contains two complete sets of tile data, with the first table at offset 0 and the second table at offset 32, so we store the results as follows: * 0 = store the results in the first table e.g. in the 32-byte table at tileViewData * 32 = store the results in the second table e.g. in the 32-byte table at tileViewData+32
Returns: tileViewData Tile data for this tile corner, stored in the relevant entry for this tile corner drawViewYaw(Hi Lo) The yaw angle, stored in the relevant entry for this tile corner drawViewPitchHi High byte of the pitch angle, stored in the relevant entry for this tile corner drawViewPitchLo Low byte of the pitch angle, stored in the relevant entry for this tile corner tileIsOnScreen Determines whether the tile corner is on-screen (i.e. within the max and min yaw angle limits): * %00000000 = tile is not on-screen and is past the left edge of the screen * %10000000 = tile is on-screen * %10000001 = tile is not on-screen and is past the right edge of the screen A The value of tileIsOnScreen is also returned in A Z flag The Z flag is set according to the value of tileIsOnScreen, so a BNE or BEQ following the call to GetTileViewAngles will act accordingly C flag The C flag is clear to indicate that we have not gone past the end of the tile row, which is used when calling this routine via GetTileEdgeToLeft or GetTileEdgeToRight Y Y is preserved
[X]
Subroutine GetHypotenuse (category: Maths (Geometry))
Calculate the hypotenuse from an angle and two triangle sides with one lookup and one multiplication (so without a square root)
[X]
Subroutine GetHypotenuseAngle (category: Maths (Geometry))
Calculate the angle of the hypotenuse in a right-angle triangle given the two non-hypotenuse sides (i.e. two orthogonal axes)
[X]
Variable drawViewYawHi (category: Drawing the landscape)
Storage for the yaw angles of tiles and object points for drawing the current landscape view (high bytes)
[X]
Variable drawViewYawLo (category: Drawing the landscape)
Storage for the yaw angles of tiles and object points for drawing the current landscape view (low bytes)
[X]
Variable drawingTableIndex in workspace Zero page
The index into the drawing tables for the tile being analysed
[X]
Variable drawingTableOffset in workspace Zero page
The offset to use within the various drawing data tables for the tile we are analysing
[X]
Variable screenLeftYawHi in workspace Zero page
The high byte of the yaw angle of the left edge of the screen, reduced into the range of a single 90-degree quadrant (so it's relative to the 90-degree viewing arc)
[X]
Label tang1 is local to this routine
[X]
Label tang2 is local to this routine
[X]
Variable tileIsOnScreen in workspace Zero page
Information on whether a tile is fully on-screen, partially on-screen or fully off-screen
[X]
Variable viewingObject in workspace Zero page
The number of the viewing object
[X]
Variable xDeltaAbsoluteHi in workspace Zero page
The absolute difference between two x-coordinates (high byte), i.e. |xDeltaHi|
[X]
Variable xTileViewer in workspace Zero page
The tile x-coordinate of the viewer, but with the axes rotated to match the orientation of the viewer, so we can draw the landscape along the line of sight, towards the viewer's tile
[X]
Variable xTitleOffset in workspace Main variable workspace
An x-coordinate offset for drawing the title screen this is zero during gameplay)
[X]
Variable yStoreTileView in workspace Zero page
Temporary storage for Y so it can be preserved through calls to GetTileViewAngles
[X]
Variable yawAdjustmentLo in workspace Zero page
A yaw adjustment to apply to the landscape drawing process so that when we update objects on-screen, we can yaw the viewer's gaze to the right to move the left edge of the object to the left edge of the screen so the object will fit into the screen buffer as efficiently as possible (low byte)
[X]
Variable zDeltaAbsoluteHi in workspace Zero page
The absolute difference between two z-coordinates (high byte), i.e. |zDeltaHi|
[X]
Variable zTileViewer in workspace Zero page
The tile z-coordinate of the viewer, but with the axes rotated to match the orientation of the viewer, so we can draw the landscape along the line of sight, towards the viewer's tile