Skip to navigation

Aviator on the BBC Micro

The Theme: ExplodeAlien

Name: ExplodeAlien [Show more] Type: Subroutine Category: The Theme Summary: Explode an alien, making the alien split apart Deep dive: Explosions and turbulence
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * MainLoop (Part 5 of 15) calls ExplodeAlien

Arguments: hitObjectId The object ID of the exploding alien (30 to 33)
.ExplodeAlien LDA hitTimer \ If hitTimer is zero then there is no exploding alien, BEQ expl6 \ so jump to expl8 via expl6 to return from the \ subroutine LDA #2 \ Otherwise we do have an exploding alien, so make sound JSR MakeSound \ #2, the sound of an alien being destroyed LDX hitObjectId \ Set X to the object ID of the object we hit (30 to 33) LDY explodeFrom-30,X \ Set Y to the "from" point ID for exploding this alien \ slot LDA explodeTo-30,X \ Set U to the "to" point ID for exploding this alien STA U \ slot LDX #2 \ Set X = 2 to act as a shift counter in the following \ loop CPX feedingStage \ If X >= feedingStage, i.e. feedingStage <= 2, then BCS expl1 \ skip the following instruction LDX feedingStage \ Set X to the feeding stage, so X now contains the \ feeding stage, capped to a maximum value of 2 .expl1 LDA #%11111111 \ We now take %11111111 and shift it right by X + 1 \ places .expl2 LSR A \ Shift X right by one place DEX \ Decrement the shift counter BPL expl2 \ Loop back until we have shifted right by X + 1 places STA P \ Store the result in P, so we get the following: \ \ * P = %01111111 if feedingStage = 0 \ * P = %00111111 if feedingStage = 1 \ * P = %00011111 if feedingStage >= 2 \ In the following outer loop, Y iterates through the \ pointIDs, starting at the "from" ID we fetched from \ above and ending at the "to" value \ \ For each point, it adds or subtracts a random number \ to the point coordinate, with the random number being \ scaled along with P (so fatter aliens have their \ points moved further) .expl3 LDX #LO(xTemp2Lo) \ Set X so the call to CopyPointToWork copies the \ coordinates to (xTemp2, yTemp2, zTemp2) JSR CopyPointToWork \ Copy the coordinates from point Y to \ (xTemp2, yTemp2, zTemp2), so it contains the \ coordinates of the next point to process in Y STY T \ Store the loop counter in T so we can retrieve it \ later \ We now add (or subtract) a random number to each \ of the three axes in the (xTemp2, yTemp2, zTemp2) \ coordinate, using a different random number for \ each axis, setting the sign of the random number \ according to bit 0 (which is random), shifting the \ number right and AND'ing with P to give us a random \ number in the following range: \ \ * -128 to +127 if feedingStage = 0 \ * -64 to +63 if feedingStage = 1 \ * -32 to +31 if feedingStage >= 2 LDY #2 \ Set an index in Y for the inner loop, to work through \ the three axes of (xTemp2, yTemp2, zTemp2), from \ zTemp2 to xTemp2 \ \ The comments below are for the x-coordinate .expl4 LDA #0 \ Set R = 0 to act as the top byte for (R A) STA R JSR NextRandomNumber \ Set A to point to the next item in the randomNumbers \ list TAX \ Set A to the random number from the randomNumbers list LDA randomNumbers+1,X LSR A \ Shift A to the right, moving bit 0 into the C flag AND P \ Set A = A AND P BCC expl5 \ If bit 0 of A before the shift was clear, skip the \ following two instructions, as we are going to leave \ (R A) as a positive number DEC R \ Otherwise we want (R A) to be negative, so decrement R \ to &FF to act as the top byte in a negative (R A) EOR #&FF \ Flip all the bits in A to negate it, so in all we have \ (R A) = ~(A AND P) .expl5 ADC xTemp2Lo,Y \ Set (xTemp2Hi xTemp2Lo) = (xTemp2Hi xTemp2Lo) + (R A) STA xTemp2Lo,Y \ \ starting with the low bytes LDA R \ And then the high bytes ADC xTemp2Hi,Y STA xTemp2Hi,Y DEY \ Decrement the loop counter to move on to the next axis BPL expl4 \ Loop back until we have done all three axes \ We have now added random numbers to all three axes in \ (xTemp2, yTemp2, zTemp2), scaled to the alien's size, \ so now to copy the result back to the original point \ coordinates LDY T \ Restore the loop counter that we stored in T, so Y now \ contains the point ID once again LDX #LO(xTemp2Lo) \ Set X so the call to CopyWorkToPoint copies the \ coordinates from (xTemp2, yTemp2, zTemp2) JSR CopyWorkToPoint \ Copy the coordinates from (xTemp2, yTemp2, zTemp2) \ to point T DEY \ Decrement the outer loop counter to move on to the \ next point in the "from" to "to" range CPY U \ Loop back until we have done the "to" point BCS expl3 DEC hitTimer \ Decrement the hit timer, to move the current explosion \ process along by 1 BNE expl6 \ If the timer is still non-zero, then the explosion \ hasn't finished, so skip the following instruction JSR ScoreHitPoints \ The alien has finished exploding, so award points for \ its destruction .expl6 LDA hitTimer \ If hitTimer <> 26, jump to expl8 to return from the CMP #26 \ subroutine BNE expl8 \ If we get here then hitTimer = 26, so it was 27 before \ the decrement above, which is right at the start \ of the explosion LDA zTemp2Hi \ Set A to the high byte of the alien's new z-coordinate LDX hitObjectId \ If we didn't hit the flying alien, jump to expl7 to CPX #33 \ set distanceFromHit to the z-coordinate BNE expl7 SEC \ We hit the flying alien, so set A = A - 8 to store in SBC #8 \ distanceFromHit, which increases the chance of \ turbulence (as turbulence only kicks in when \ distanceFromHit < 16) BPL expl7 \ If the subtraction reduced A to below zero, set A = 0 LDA #0 \ to store in distanceFromHit .expl7 STA distanceFromHit \ Store the z-coordinate (or the z-coordinate - 8) in \ distanceFromHit, so turbulence will be applied if we \ are too close to the alien .expl8 RTS \ Return from the subroutine