![]() |
Routines |
| Prev: A727 | Up: Map | Next: A81E |
|
Used by the routine at MainLoop.
Called every frame while the robot is alive. It tries to start a new enemy at a random position in the sector that the robot is in, and tries to start a new destroyer in the sector that is under attack. A new enemy starts as the sprites that show it materialising. The enemy is only started if there is a free entity, and if the cell that is chosen at random is empty.
|
||||
| SpawnEnemies | A739 | LD A,($9690) | Fetch the type of the robot. | |
| A73C | CP $10 | Return if it is below 10. | ||
| A73E | RET C | |||
| A73F | CP $30 | Return if it is 30 or above, as the robot is not in a walking state. | ||
| A741 | RET NC | |||
| A742 | LD HL,$96D0 | Point HL at the first of the six entities that are used for enemies. | ||
| A745 | LD DE,$0010 | Each entity is 10 bytes long. | ||
| A748 | LD B,$06 | There are six entities to check. | ||
| SpawnEnemies_Find | A74A | LD A,(HL) | Fetch the type of the entity. | |
| A74B | AND A | Jump if it is not in use. | ||
| A74C | JR Z,SpawnEnemies_UseFirstEntity | |||
| A74E | ADD HL,DE | Move on to the next entity. | ||
| A74F | DJNZ SpawnEnemies_Find | Loop back until all of them have been tried. | ||
| A751 | JR SpawnEnemies_Destroyer | Jump to try to start a destroyer. | ||
| SpawnEnemies_UseFirstEntity | A753 | PUSH HL | Copy the address of the entity into IX... | |
| A754 | POP IX | Pop it into IX. | ||
| A756 | LD B,$10 | There are 10 bytes to clear. | ||
| SpawnEnemies_Clear | A758 | LD (HL),$00 | Clear a byte of the entity. | |
| A75A | INC HL | Move on to the next byte. | ||
| A75B | DJNZ SpawnEnemies_Clear | Loop back until the entity has been cleared. | ||
| A75D | LD A,($9692) | Fetch the X cell of the camera... | ||
| A760 | AND $30 | ...and keep the sector (a multiple of 10). | ||
| A762 | LD E,A | Keep the sector column of the camera. | ||
| A763 | LD A,($9617) | Fetch the random number... | ||
| A766 | AND $0F | ...limited to 00-0F... | ||
| A768 | OR E | ...and combine it with the sector to choose the X cell. | ||
| A769 | CP $2F | Jump if it is outside the map, which is 30 cells wide. | ||
| A76B | JR NC,SpawnEnemies_Destroyer | |||
| A76D | LD D,A | Keep the X cell... | ||
| A76E | LD E,$00 | ...and use zero for the fraction. | ||
| A770 | LD A,($9694) | Fetch the Y cell of the camera... | ||
| A773 | AND $30 | ...and keep the sector. | ||
| A775 | LD L,A | Keep the sector row of the camera. | ||
| A776 | LD A,($9615) | Fetch the frame counter... | ||
| A779 | AND $0F | ...limited to 00-0F... | ||
| A77B | OR L | ...and combine it with the sector to choose the Y cell. | ||
| A77C | CP $2F | Jump if it is outside the map, which is 30 cells high. | ||
| A77E | JR NC,SpawnEnemies_Destroyer | |||
| A780 | LD H,A | Keep the Y cell... | ||
| A781 | LD L,$00 | ...and use zero for the fraction. | ||
| A783 | CALL FindMapCell | Find the cell using FindMapCell. | ||
| A786 | JR NZ,SpawnEnemies_Destroyer | Jump if it is not empty. | ||
| A788 | LD (IX+$00),$40 | Start the enemy with the first sprite of the sequence that shows it materialising. | ||
| A78C | CALL SetPosition | Store its position. | ||
| A78F | CALL CheckEnemyOverlap | Check whether another enemy is in the way using CheckEnemyOverlap. | ||
| A792 | JR NC,SpawnEnemies_Random | Jump if there is not. | ||
| A794 | LD (IX+$00),$00 | Otherwise cancel the new enemy... | ||
| A798 | JR SpawnEnemies_Destroyer | ...and jump to try to start a destroyer. | ||
| SpawnEnemies_Random | A79A | LD A,R | Fetch a number from the memory refresh register... | |
| A79C | AND $F3 | ...limit it to a time and a direction... | ||
| A79E | LD (IX+$07),A | ...and store it. | ||
| A7A1 | LD A,($9658) | Fetch the number of sectors that have been activated. | ||
| A7A4 | AND A | Test whether there are any. | ||
| A7A5 | LD A,($9617) | Fetch the random number. | ||
| A7A8 | JR NZ,SpawnEnemies_AnyKind | Jump if some sectors have been activated, to use any of the kinds of enemy. | ||
| A7AA | AND $05 | Otherwise limit the choice to the first two kinds of enemy... | ||
| SpawnEnemies_AnyKind | A7AC | AND $07 | ...and limit the choice to the eight entries of the table. | |
| A7AE | LD L,A | Use it as an index... | ||
| A7AF | LD H,$00 | |||
| A7B1 | LD BC,$A81E | Point BC at EnemyTypes. | ||
| A7B4 | ADD HL,BC | Add the index. | ||
| A7B5 | LD A,(HL) | Fetch the type that the enemy is going to have... | ||
| A7B6 | LD (IX+$05),A | ...and store it. | ||
|
Now try to start a destroyer. Destroyers are only started while a sector is under attack.
|
||||
| SpawnEnemies_Destroyer | A7B9 | LD HL,$9730 | Point HL at the first of the four entities that are used for destroyers. | |
| A7BC | LD DE,$0010 | Each entity is 10 bytes long. | ||
| A7BF | LD B,$04 | There are four entities to check. | ||
| SpawnEnemies_FindDestroyer | A7C1 | LD A,(HL) | Fetch the type of the entity. | |
| A7C2 | AND A | Jump if it is not in use. | ||
| A7C3 | JR Z,SpawnEnemies_UseSecondEntity | |||
| A7C5 | ADD HL,DE | Move on to the next entity. | ||
| A7C6 | DJNZ SpawnEnemies_FindDestroyer | Loop back until all of them have been tried. | ||
| A7C8 | RET | Return. | ||
| SpawnEnemies_UseSecondEntity | A7C9 | PUSH HL | Copy the address of the entity into IX... | |
| A7CA | POP IX | Pop it into IX. | ||
| A7CC | LD B,$10 | There are 10 bytes to clear. | ||
| SpawnEnemies_ClearDestroyer | A7CE | LD (HL),$00 | Clear a byte of the entity. | |
| A7D0 | INC HL | Move on to the next byte. | ||
| A7D1 | DJNZ SpawnEnemies_ClearDestroyer | Loop back until the entity has been cleared. | ||
| A7D3 | LD A,($9647) | Fetch the code of the sector that is under attack... | ||
| A7D6 | LD C,A | ...and keep it in C. | ||
| A7D7 | RRA | Move the bits for the row into place... | ||
| A7D8 | RRA | Shift the row one more place. | ||
| A7D9 | AND $30 | ...and keep them. | ||
| A7DB | CP $30 | Return if there is no sector under attack. | ||
| A7DD | RET Z | |||
| A7DE | XOR $30 | Turn the row upside down... | ||
| A7E0 | SUB $10 | ...and use it to find the Y cell of the sector. | ||
| A7E2 | LD H,A | Keep the Y cell. | ||
| A7E3 | LD A,($9617) | Fetch the random number... | ||
| A7E6 | AND $0F | ...limited to 00-0F... | ||
| A7E8 | OR H | ...and combine it with the sector to choose the Y cell... | ||
| A7E9 | LD H,A | ...and keep it in H. | ||
| A7EA | LD A,C | Fetch the code of the sector again. | ||
| A7EB | RLA | Move the bits for the column into place... | ||
| A7EC | RLA | |||
| A7ED | RLA | |||
| A7EE | AND $30 | ...and keep them. | ||
| A7F0 | CP $30 | Return if there is no sector under attack. | ||
| A7F2 | RET Z | |||
| A7F3 | LD D,A | Keep the sector. | ||
| A7F4 | LD A,R | Fetch a number from the memory refresh register... | ||
| A7F6 | AND $0F | ...limited to 00-0F... | ||
| A7F8 | OR D | ...combine it with the sector to choose the X cell... | ||
| A7F9 | LD D,A | ...and keep it in D. | ||
| A7FA | LD L,$00 | Use zero for the fraction of the Y position... | ||
| A7FC | LD E,L | ...and of the X position. | ||
| A7FD | CALL FindMapCell | Find the cell using FindMapCell. | ||
| A800 | RET NZ | Return if it is not empty. | ||
| A801 | LD (IX+$00),$40 | Start the destroyer with the first sprite of the sequence that shows it materialising. | ||
| A805 | CALL SetPosition | Store its position. | ||
| A808 | CALL CheckEnemyOverlap | Check whether another enemy is in the way using CheckEnemyOverlap. | ||
| A80B | JR NC,SpawnEnemies_SetType | Jump if there is not. | ||
| A80D | LD (IX+$00),$00 | Otherwise cancel the new destroyer... | ||
| A811 | RET | ...and return. | ||
| SpawnEnemies_SetType | A812 | LD (IX+$05),$64 | Set the type that the destroyer will have when it has materialised. | |
| A816 | LD A,R | Choose a random direction and time... | ||
| A818 | AND $F3 | |||
| A81A | LD (IX+$07),A | ...and store it. | ||
| A81D | RET | Return. | ||
| Prev: A727 | Up: Map | Next: A81E |