.GetTileAltitude JSR GetTileData \ Set A to the tile data for the tile anchored at \ (xTile, zTile), setting the C flag if the tile \ contains an object BCS tile3 \ If the tile contains an object then jump to tile3 PHA \ Store the tile data on the stack AND #%00001111 \ The tile shape is in the low nibble of the tile data, TAY \ so extract the tile shape into Y PLA \ Retrieve the tile data from the stack LSR A \ Set A to the tile altitude, which is in the top nibble LSR A \ of the tile data LSR A LSR A CPY #1 \ Clear the C flag if Y < 1, which will only happen when \ Y = 0, so this clears the C flag if the tile shape is \ flat, or sets the C flag if the tile shape is not flat RTS \ Return from the subroutine .tile1 \ If we get here then the tile contains object #Y and \ bit 7 of considerObjects is set, so we need to process \ the objects on the stack CPY targetObject \ If Y = targetObject then the target object is on the BNE tile2 \ tile, so set bit 7 of targetOnTile to indicate this ROR targetOnTile .tile2 LDA objectTypes,Y \ Set A to the type of object that's already on the tile \ (i.e. the type of object #Y) CMP #3 \ If the tile contains a boulder (an object of type 3), BEQ tile4 \ jump to tile4 to extract details about the boulder CMP #2 \ If the tile contains a tree (an object of type 2), BEQ tile4 \ jump to tile4 to extract details about the tree CMP #6 \ If the tile doesn't contain the Sentinel's tower (type BNE tile7 \ 6) then it must contain a robot, sentry, meanie or the \ Sentinel, so jump to tile7 to return the altitude of \ the tile rather than the object \ If we get here then the tile contains the Sentinel's \ tower in object #Y JSR CheckForTileCentre \ Set T = max(|xCoordLo - 128|, |zCoordLo - 128|) \ \ and return the same value in A \ \ This calculates how close the current position along \ the gaze vector is to the centre of the tile, in terms \ of the x-coordinate and z-coordinate CMP #100 \ If A >= 100 then the gaze vector is a long way from BCS tile6 \ the centre of the tile (i.e. more than 100/128 = 78% \ of the distance from the centre to the tile edge, \ which is outside the body of the tower), so jump to \ tile6 to set bit 6 of considerObjects and return the \ altitude of the tile \ If we get here then the gaze vector is pointing at the \ sides of the tower, so we return the altitude of the \ platform on top of the tower LDA #16 \ Set yAccuracyLo = 16, so the gaze vector has to be STA yAccuracyLo \ no more than 0.025 of a tile's height above the tile \ for us to consider it as potentially hitting the tile \ when we return to the FollowGazeVector routine (this \ makes the player have to be much more accurate when \ trying to view the Sentinel's tile) LDA yObjectLo,Y \ Set the following: CLC \ ADC #&20 \ (A yPlatformLo) = yObject(Hi Lo) + 32 STA yPlatformLo \ LDA yObjectHi,Y \ where yObject is the altitude of the Sentinel's tower ADC #&00 \ \ So we return the altitude of the top of the tower by \ effectively adding the tower's height to the tower \ object's altitude, bearing in mind that objects are \ spawned at a height of 224 above their tiles, so this \ returns the altitude of the top of the tower, with \ the tower being 224 + 32 = 256 fractional parts above \ the tile (so the tower is the height of one entire \ integer y-coordinate) CLC \ Clear the C flag to indicate that the tile is flat RTS \ Return from the subroutine .tile3 \ If we get here then the tile contains an object AND #%00111111 \ Because the tile has an object on it, the tile data TAY \ contains the number of the top object on the tile in \ bits 0 to 5, so extract the object number into Y (so \ the tile effectively contains object #Y) BIT considerObjects \ If bit 7 of considerObjects is clear, jump to tile7 to BPL tile7 \ return the altitude of the bottom object on the tile, \ iterating down through the stack of objects if there \ is more than one object \ \ The altitude of the bottom object is the same as the \ altitude of the tile itself, so this ensures that we \ return the tile's altitude from the subroutine, as per \ bit 7 of considerObjects BMI tile1 \ Otherwise bit 7 of considerObjects is set and we need \ to take any objects on the tile into consideration, so \ jump to tile1 to process the objects on the stack \ (this BMI is effectively a JMP as we just passed \ through a BPL) .tile4 \ If we get here then the tile contains a tree or a \ boulder in object #Y JSR CheckForTileCentre \ Set T = max(|xCoordLo - 128|, |zCoordLo - 128|) \ \ and return the same value in A \ \ This calculates how close the current position along \ the gaze vector is to the centre of the tile, in terms \ of the x-coordinate and z-coordinate CMP #64 \ If A >= 64 then the gaze vector is more than half way BCS tile6 \ from the centre of the tile (i.e. more than 64/128 = \ 50% of the distance from the centre to the tile edge, \ which is outside the body of the tree or boulder), so \ jump to tile6 to set bit 6 of considerObjects (if this \ is a boulder) and return the altitude of the tile LDA objectTypes,Y \ If object #Y is a tree (an object of type 2), jump to CMP #2 \ tile5 BEQ tile5 \ If we get here then the tile contains a boulder in \ object #Y SEC \ Set bit 7 of boulderOnTile to indicate that the tile ROR boulderOnTile \ contains a boulder LDA yObjectLo,Y \ Set the following: SEC \ SBC #&60 \ (A yPlatformLo) = yObject(Hi Lo) - 96 STA yPlatformLo \ LDA yObjectHi,Y \ where yObject is the altitude of the boulder SBC #&00 \ So we return the altitude of the top of the boulder by \ effectively adding the boulder's height to the boulder \ object's altitude, bearing in mind that objects are \ spawned at a height of 224 above their tiles, so this \ returns the altitude of the top of the boulder, with \ the boulder being 224 - 96 = 128 fractional parts \ above the tile (so the boulder is the height of one \ half of a y-coordinate) CLC \ Clear the C flag to indicate that the tile is flat RTS \ Return from the subroutine .tile5 \ If we get here then the tile contains a tree in \ object #Y LDA yObjectLo,Y \ Set the following: SEC \ SBC yCoordLo \ (A U) = yObject(Hi Lo) - yCoord(Hi Lo) STA U \ LDA yObjectHi,Y \ where yObject is the altitude of the tree SBC yCoordHi \ \ So (A U) contains the relative altitude of the current \ position along the gaze vector compared to the tree, \ with a positive value indicating that the gaze is \ is below the tree, and a negative value indicating \ that the gaze is above the tree PHA \ Set (A U) = (A U) + 224 LDA U \ CLC \ This adds the height of the tree to (A U), as trees ADC #&E0 \ have a height of 224 fractional y-coordinates, so the STA U \ value in (A U) is now relative to the top of the tree, PLA \ so it is effectively the height difference between the ADC #&00 \ gaze and the tree top BMI tile6 \ If A is negative then the current position along the \ gaze vector is above the top of the tree, so jump to \ tile6 to return the altitude of the tile LSR A \ Set (A U) = (A U) / 2 ROR U \ \ So (A U) is now half the height difference between the \ gaze and tree top LSR A \ If any of bits 1 to 7 of A are set then A >> 1 will be BNE tile6 \ non-zero and the original value of (A U) must have \ been at least %100, so that's a positive value with a \ high byte of at least 4 \ \ This means the gaze vector is too far below the tree \ for it to be visible, so jump to tile6 to return the \ altitude of the tile LDA U \ If we get here then we know A >> 1 = 0, so we can ROR A \ halve (U A) again and discard the top byte, as it will \ be zero, so this sets: \ \ A = (U A) / 2 \ \ So this is the original height difference between the \ gaze and tree top, divided by 4 \ We set T above to the maximum distance between the \ gaze vector and the centre of the tile in terms of the \ horizontal axes CMP T \ If A < T then the gaze is further from the centre of BCC tile6 \ the tile than the height difference to the tree top \ divided by 4, so jump to tile6 to return the altitude \ of the tile \ \ The centre point of the tile is the tree trunk, so \ this test means that gazes at the lower parts of the \ tree can be further from the centre point than gazes \ at the upper parts of the tree, while still being \ considered gazes that fall upon the tree \ \ This fits in with the tree's shape and makes the tree \ detection code more accurate BIT targetOnTile \ If bit 7 of targetOnTile is set then the tree is BMI tile6 \ the targeted object, so skip the following so that we \ only set bit 7 of gazeCanSeeTree if the tree is not \ the target (i.e. if bit 7 of targetOnTile is clear) SEC \ Set bit 7 of gazeCanSeeTree to indicate that the tree ROR gazeCanSeeTree \ can be seen by the gaze vector .tile6 LDA objectTypes,Y \ Set A to the type of object #Y CMP #2 \ If the tile contains a tree (an object of type 2), BEQ tile7 \ jump to tile7 to skip the following instruction \ If we get here then the tile contains a boulder or the \ Sentinel's tower, and in either case the gaze vector \ is not close enough to the platform object to hit it LDA #%11000000 \ Set bit 6 of considerObjects to denote that the gaze STA considerObjects \ vector is passing close by the platform object but is \ not hitting it, and set bit 7 so that it is unchanged .tile7 LDA objectFlags,Y \ Set A to the object flags for object #Y CMP #%01000000 \ If bit 6 of the object flags for object #Y is set BCS tile3 \ then object #Y is stacked on top of another object, \ so jump to tile3 with the object number in bits 0 to \ 5 of the object flags in A, so we can process that \ object instead LDA yObjectHi,Y \ At this point we have reached the object on the tile \ itself, so set A to the y-coordinate of that object, \ which will be the tile altitude, and return from the \ subroutine with the C flag clear to denote a flat \ tile, as objects are only ever placed on flat tiles RTS \ Return from the subroutineName: GetTileAltitude [Show more] Type: Subroutine Category: Landscape Summary: Calculate the altitude of a tile, optionally including platform objects and trees in the calculationContext: See this subroutine in context in the source code References: This subroutine is called as follows: * FollowGazeVector (Part 1 of 5) calls GetTileAltitude * FollowGazeVector (Part 2 of 5) calls GetTileAltitude * GetTileAltitudes calls GetTileAltitude
Arguments: (xTile, zTile) The coordinates of the tile to analyse considerObjects The data to extract: * Bit 7 clear = extract the tile's altitude and flatness, ignoring any objects on the tile * Bit 7 set = if the tile contains a platform object (i.e. boulder or tower) or a tree, then extract data for the object instead of the tile when applicable (this option is only set when calling this routine from FollowGazeVector) xCoordLo The low byte (i.e. fractional part) of the x-coordinate of the current position along the gaze vector (when the routine is called from FollowGazeVector) zCoordLo The low byte (i.e. fractional part) of the z-coordinate of the current position along the gaze vector (when the routine is called from FollowGazeVector)
Returns: A The high byte of the tile's altitude (though if bit 7 of considerObjects is set, see yPlatformLo below) C flag The tile's shape: * Clear if the tile is flat * Set if the tile is not flat yPlatformLo If bit 7 of considerObjects is set and the tile contains the Sentinel's tower or a boulder, the altitude of the platform on the top of the tower or boulder is returned in (A yPlatformLo) boulderOnTile If bit 7 of considerObjects is set, this records whether the tile contains a boulder: * Bit 7 clear = tile does not contain a boulder * Bit 7 set = tile contains a boulder targetOnTile If bit 7 of considerObjects is set, this records whether the tile contains the target object whose number is in targetOnTile: * Bit 7 clear = tile does not contain the target object * Bit 7 set = tile does contain the target object gazeCanSeeTree If bit 7 of considerObjects is set and bit 7 of targetOnTile is clear, this records whether the tile contains a tree that can be seen by the gaze vector: * Bit 7 clear = tile does not contain a tree that can be seen by the gaze vector * Bit 7 set = tile contains a tree that can be seen by the gaze vector considerObjects If bit 7 of considerObjects is set then bit 6 will also be set by the routine if the tile contains a platform object (i.e. boulder or Sentinel's tower) and the current position along the gaze vector is not within the platform object (so the gaze vector is passing close by the platform object but is not hitting it) yAccuracyLo Set to 16 if the tile contains the Sentinel's tower and the gaze vector is pointing at the sides of the tower
[X]
Subroutine CheckForTileCentre (category: Maths (Geometry))
Calculate max(|xCoordLo - 128|, |zCoordLo - 128|)
[X]
Subroutine GetTileData (category: Landscape)
Get the tile data and tile data address for a specific tile
[X]
Variable boulderOnTile in workspace Main variable workspace
A flag to record whether the tile being analysed in the GetTileAltitude routine contains a boulder
[X]
Variable considerObjects in workspace Zero page
Controls whether the GetTileAltitude routine takes platform objects into consideration when calculating tile altitudes (bit 7) and returns details about the gaze vector (bit 6)
[X]
Variable gazeCanSeeTree in workspace Main variable workspace
A flag to record whether the gaze vector can see a tree
[X]
Variable objectFlags in workspace Stack variables
Object flags for up to 64 objects
[X]
Variable objectTypes (category: 3D objects)
The object types table for up to 64 objects
[X]
Variable targetObject in workspace Main variable workspace
The number of the object that is being targeted in the DrainObjectEnergy routine
[X]
Variable targetOnTile in workspace Main variable workspace
A flag to record whether the tile being analysed in the GetTileAltitude routine contains the target object whose number is in targetObject
[X]
Label tile1 is local to this routine
[X]
Label tile2 is local to this routine
[X]
Label tile3 is local to this routine
[X]
Label tile4 is local to this routine
[X]
Label tile5 is local to this routine
[X]
Label tile6 is local to this routine
[X]
Label tile7 is local to this routine
[X]
Variable yAccuracyLo in workspace Zero page
The vertical accuracy for considering a tile as being seen by the viewer, as a fractional part
[X]
Variable yObjectHi (category: 3D objects)
The y-coordinates in 3D space for the 3D objects (high byte)
[X]
Variable yObjectLo (category: 3D objects)
The y-coordinates in 3D space for the 3D objects (low byte)
[X]
Variable yPlatformLo in workspace Zero page
The low byte of the altitude of the Sentinel's tower or boulder when returning tile data from the GetTileAltitude routine