References: Supporting documentation, http://users.picbasic.org/projects/S...e_invaders.htm,
' Experimental software to reproduce the classic Space Invaders game
' For version 2.1 of the PROTON+ BASIC Compiler
' Written by Les Johnson 2003.
'
' This version uses the LCDWRITE and PLOT commands to produce the graphics
' Which allows smooth movements on a pixel by pixel basis
'
' Use an 8MHz crystal
'
' BUTTON CONNECTIONS
' LEFT Button connects to PORTB.0
' RIGHT Button connects to PORTB.1
' FIRE Button connects to PORTB.2
'
' SOUND CHANNEL CONNECTIONS
' Each channel is output from PORTA.0,1,2
' Channel 1. PORTA.0 is the INVADER noise
' Channel 2. PORTA.1 is the MISSILE noise
' Channel 3. PORTA.2 is the SAUCER noise
' Each pin should have a current limiting resistor in order to stop pin to pin shorts.
'
' 1uF
' 220 +| |-
' PORTA.0 --/\/\/\----| |--- To SPEAKER
' | | |
' 330 |
' PORTA.1 --/\/\/\--|
' |
' 330 |
' PORTA.2 --/\/\/\--|
'
'
' * Revision 1.0 10 September 2003
'
' Ship moving smoothly and missile working correctly
'
' * Revision 1.1 10 September 2003
'
' Invaders moving left to right and down (got a problem with alignment when moving down)
' Invaders become faster as they move down
' Invader erased when missile hits, and hit counter incremented
' Bases require five hits per section before they dissapear
' There are 9 sections, three in each base
' A new sheet of invaders is created when all of them are hit
' The new sheet is slightly faster than the previous one
'
' * Revision 1.2 11 September 2003
'
' Invaders now move down the screen without alignment problems
' Started placing subroutines to enable the invaders to fire back at the ship
' Placed the base hit check as a subroutine so that the invader's missile can also
' be checked for a base hit.
' Invaders can now fire back, but cannot detect any hits yet.
' Both the ship's and the invader's missiles are slowed down but still need some work.
'
' * Revision 1.3 12 September 2003
'
' Both the ship's and the invaders missiles have independant speed controls
' Invader's missile now detect whether it has hit a base, and alters the base accordingly
' Still a problem with the invader's missile hitting the base, sometimes destroys it with one blow
' Game now detects whether the invaders have reached the bottom of the screen. In which case, GAME OVER
' If the invaders reach the bases, then the bases are disabled
' Invaders now have animated characters
' Bases also have animated characters that destroy with every hit with a missile
' The ship now only moves one pixel at a time instead of two. This slow the ship to a reasonable speed
' The invaders speed up whenever one is hit, and also speed up by a factor of 3 when there are 4 or less invaders left
' Invaders also speed up whenever they move down the screen
' Added simple sound effects when invaders move. This will be altered later.
'
' * Revision 1.4 13 September 2003
'
' Flying saucer now moves right to left at the top of the screen
' Missile to missile collisions are now detected
'
' * Revision 1.5 14 September 2003
'
' Missiles are now implemented using the PLOT command for smooth movement
' As the invaders move down the screen their missile speed slows down slightly
' Game now detects a hit on the flying saucer at the top of the screen
' There is still a problem with the invaders and the ship hitting the bases
' The base counter is decremented too quickly, or destroyed with a single hit
'
' * Revision 1.6 18 September 2003
'
' Added scoring for invaders and saucer
' Invaders score 20 points for top row, 10 points for middle row, and 5 points for bottom row
' Saucer scores 100 points if hit
' A small animation of the points scored is also included if the saucer or invaders are hit.
' Added simple sound effects for invaders, saucer and missile shot.
'
' * Revision 1.7 27 September 2003
'
' Added second missile for space invaders, but still requires some work
' because the spread of missiles is uneven.
'
' * Revision 1.8 28 September 2003
'
' Replaced sound using the SOUND command with interrupt driven sounds
' There are three independant sound channels from PORTA0,1,2
' Each is capable of producing a different frequency, and channel one (INVADER channel) also has a duration.
' With the interrupt driven sound, I have had to increase the crystal to 8MHz.
' Each layer of invader now has a different invader sprite, each consisting of two characters.
' Created new user defined shape for saucer and ship.
' Saucer now scores 100+ points if hit. More points gained the closer to the right hand side of the screen.
' Added levels to the game. After level 10 the invaders start firing two missiles.
'
' * Revision 1.9 01 October 2003
'
' Invader to Ship missile collision detection is now implemented
' Each time the ship is hit a life is decremented.
' After three lives the game is over.
' Added a splash screen when the game first starts
'
' * Revision 2 04 October 2003
'
' Score increases by one if a missile hits a missile
' If there are only 1 or 2 invaders left on the screen their speed increases dramatically
' When all the ship's lives are lost, a large circular explosion occurs.
'
'
'
' See if thare are any improvements you can make, and report them on the Forum!
'
Include "PROTON_G8.INT" ' Game created on the PROTON board
' Set up some Variables
' Interrupt driven sound channel variables
Dim NOTE_STATUS as Byte SYSTEM
Dim INVADER_SOUND_ENABLE as NOTE_STATUS.0
Dim MISSILE_SOUND_ENABLE as NOTE_STATUS.1
Dim SAUCER_SOUND_ENABLE as NOTE_STATUS.2
Dim INTERNAL_INVADER_SOUND_ENABLE as NOTE_STATUS.4
Dim INTERRUPT_COUNTER1 as Byte SYSTEM
Dim INVADER_SOUND_COUNTER as Byte SYSTEM
Dim INVADER_FREQ as Byte SYSTEM
Dim INVADER_SOUND_DURATION as Byte SYSTEM
Dim INVADER_SOUND_DURATION_COUNTER as Byte SYSTEM
Dim MISSILE_SOUND_COUNTER as Byte SYSTEM
Dim MISSILE_FREQ as Byte SYSTEM
Dim SAUCER_SOUND_COUNTER as Byte SYSTEM
Dim SAUCER_FREQ as Byte SYSTEM
' Space invader variables
Dim BASE_ENABLED[9] as Byte ' Whether or not the section of the BASE is enabled
Dim BASE_HITS[9] as Byte ' Holds the amount of hits each part of the bases has had
Dim INVADER_XPOS[18] as Byte' at 400 ' Array to hold the space invader's X position
Dim INVADER_YPOS[18] as Byte' at 418 ' Array to hold the space invader's Y position
Dim INVADER_ENABLED[18] as Byte' at 436 ' Array to hold the space invader' config. i.e. hit or active
Dim SHIP_XPOS as Byte ' X position of BASE ship
Dim MISSILE_YPOS as Byte ' Y position of Ship's MISSILE
Dim MISSILE_XPOS as Byte ' X position of Ship's MISSILE
Dim MISSILE_STATUS as Byte SYSTEM
Dim MISSILE_FIRED as MISSILE_STATUS.0 ' TRUE if Ship's MISSILE in the air
Dim MISSILE_HIT as MISSILE_STATUS.1 ' Set if Ship's missile has hit something
Dim TIME_TO_MOVE_INVADERS as MISSILE_STATUS.7 ' Indicate time to move the invaders
Dim BASE_HIT as MISSILE_STATUS.2 ' Indicates whether a BASE has been hit by a missile
Dim TIME_TO_MOVE_SHIP_MISSILE as MISSILE_STATUS.3 ' Indicate time to move the ship's missile
Dim TIME_TO_MOVE_BASE as Bit
Dim SHIP_SPEED as Byte
Dim INVADER_TICK as Byte ' Constant tick within program
Dim INVADER_LOOP as Byte SYSTEM ' Scans the invader arrays
Dim INVADER_MISSILE_TICK as Byte
Dim SHIP_MISSILE_TICK as Byte
Dim TEMP_LOOP as Byte
Dim INVADERS_DIRECTION as Bit
Dim INVADERS_ENABLED as Byte ' Count the INVADERS enabled
Dim INVADER_SPEED as Byte ' The speed of the invaders
Dim BASE_XPOS_TEST as Byte ' Used for detecting a missile hit on a BASE
Dim SHIP_HIT as Bit ' TRUE if ship hit by missile
Dim INVADER_MISSILE_YPOS as Byte ' Y position of Invader's MISSILE
Dim INVADER_MISSILE_XPOS as Byte ' X position of Invader's MISSILE
Dim TIME_TO_MOVE_INV_MISSILE as MISSILE_STATUS.4 ' Indicate time to move the invader's missile
Dim INVADER_MISSILE_FIRED as MISSILE_STATUS.5 ' TRUE if Invader's MISSILE in the air
Dim INVADER_MISSILE_HIT as MISSILE_STATUS.6 ' Set if Invader's missile has hit something
Dim TIME_TO_MOVE_INVADERS_DOWN as Bit ' Signal that the invaders need to move down
Dim INVADERS_REACHED_BOTTOM as Bit ' Set if the invaders reach the botton of the screen
Dim INVADER_MISSILE_SPEED as Byte ' The speed of the invader's missile. This slows down as invader near the bottom of the screen
Dim DEFAULT_INVADER_SPEED as Byte ' Saves the initial speed of the invaders
Dim INVADER_CHARACTER as Bit ' Determines the character to use for the invader
Dim INVADER_MISSILE2_TICK as Byte
Dim INVADER_MISSILE2_YPOS as Byte ' Y position of Invader's second MISSILE
Dim INVADER_MISSILE2_XPOS as Byte ' X position of Invader's second MISSILE
Dim TIME_TO_MOVE_INV_MISSILE2 as Bit ' Indicate time to move the invader's second missile
Dim INVADER_MISSILE2_FIRED as Bit ' TRUE if Invader's second MISSILE in the air
Dim INVADER_MISSILE2_HIT as Bit ' Set if Invader's second missile has hit something
Dim INVADER_MISSILE2_SPEED as Byte ' The speed of the invader's second missile. This slows down as invader near the bottom of the screen
Dim SAUCER_XPOS as Byte
Dim SAUCER_HIT as Bit
Dim TIME_TO_MOVE_SAUCER as Bit
Dim SAUCER_SPEED as Byte
Dim SAUCER_ENABLED as Bit
Dim SCORE as Dword ' Holds the games score
Dim LEVEL as Word ' Game level
Dim LIVES as Byte ' Amount of lives left for the base
' Define some constants and alias's
Symbol L_BUTTON = PORTB.0
Symbol R_BUTTON = PORTB.1
Symbol FIRE_BUTTON = PORTB.2
Symbol SPEAKER = PORTB.3
Symbol SHIP_WIDTH = 9 ' The width of the ship in pixels. This does not include the two blanks
Symbol INVADER_WIDTH = 10 ' The width of the invaders. minus the two outside blanks
Symbol INVADER_RIGHT_LIMIT = 127 - INVADER_WIDTH ' The right most limit for the invaders before they need to move down
Symbol SAUCER_WIDTH = 14
Symbol TRUE = 1
Symbol FALSE = 0
Symbol FORWARD = 1
Symbol BACKWARD = 0
Symbol T0IF INTCON.2 ' Timer0 Overflow Interrupt Flag
Symbol GIE INTCON.7 ' Global Interrupt Enable
ON_INTERRUPT Goto NOTE_INT
'----------------------------------------------------------------------------
Input L_BUTTON
Input R_BUTTON
Input FIRE_BUTTON
Delayms 200 ' Wait for the PICŪ micro to stabilise
PORTB_PULLUPS = ON
Cls ' Clear the LCD
Goto MAIN_PROGRAM_LOOP ' Jump over any subroutines
'----[NOTE GENERATING INTERRUPT HANDLER]---------------------------------------------------
NOTE_INT:
TMR0 = 200
Incf INVADER_SOUND_COUNTER,F
Incf MISSILE_SOUND_COUNTER,F
Incf SAUCER_SOUND_COUNTER,F
Incf INTERRUPT_COUNTER1,F
Btfss INTERRUPT_COUNTER1,6 ' If INTERRUPT_COUNT.6 = 1
Jump INVADER_SOUND_LOOP
Clrf INTERRUPT_COUNTER1 ' INTERRUPT_COUNT = 0
Bcf INTERNAL_INVADER_SOUND_ENABLE ' INTERNAL_INVADER_SOUND_ENABLE = 0
Movfw INVADER_SOUND_DURATION_COUNTER ' If((INVADER_SOUND_DURATION_COUNTER <= INVADER_SOUND_DURATION) && (INVADER_SOUND_ENABLE == 1))
Subwf INVADER_SOUND_DURATION,W
Btfss STATUS,C
Jump FINISH_NOTE1
Btfss INVADER_SOUND_ENABLE
Jump FINISH_NOTE1
Incf INVADER_SOUND_DURATION_COUNTER,F ' INVADER_SOUND_DURATION_COUNTER++
Bsf INTERNAL_INVADER_SOUND_ENABLE ' INTERNAL_INVADER_SOUND_ENABLE = 1
Jump INVADER_SOUND_LOOP ' Otherwise
FINISH_NOTE1:
BCF INVADER_SOUND_ENABLE ' INVADER_SOUND_ENABLE = 0
CLRF INVADER_SOUND_DURATION_COUNTER ' INVADER_SOUND_DURATION_COUNTER = 0
INVADER_SOUND_LOOP:
Movfw INVADER_FREQ ' If INVADER_SOUND_COUNTER >= INVADER_FREQ
Subwf INVADER_SOUND_COUNTER,W
Btfss STATUS,C
Jump MISSILE_SOUND_LOOP
Clrw
Btfsc INTERNAL_INVADER_SOUND_ENABLE
Movlw 1 ' Set for tone generation on PORTA.0
Xorwf PORTA,F ' PORTA = PORTA ^ 1
Clrf INVADER_SOUND_COUNTER ' INVADER_SOUND_COUNTER = 0
MISSILE_SOUND_LOOP:
Movfw MISSILE_FREQ ' If MISSILE_SOUND_COUNTER >= MISSILE_FREQ
Subwf MISSILE_SOUND_COUNTER,W
Btfss STATUS,C
Jump SAUCER_SOUND_LOOP
Clrw
Btfsc MISSILE_SOUND_ENABLE
Movlw 2 ' Set for tone generation on PORTA.1
Xorwf PORTA,F ' PORTA = PORTA ^ 2
Clrf MISSILE_SOUND_COUNTER ' MISSILE_SOUND_COUNTER = 0
SAUCER_SOUND_LOOP:
Movfw SAUCER_FREQ ' If SAUCER_SOUND_COUNTER >= SAUCER_FREQ
Subwf SAUCER_SOUND_COUNTER,W
Btfss STATUS,C
Jump EXIT_INTERRUPT
Clrw
Btfsc SAUCER_SOUND_ENABLE
Movlw 4 ' Set for tone generation on PORTA.2
Xorwf PORTA,F ' PORTA = PORTA ^ 4
Clrf SAUCER_SOUND_COUNTER ' SAUCER_SOUND_COUNTER = 0
EXIT_INTERRUPT:
T0IF = 0
Context Restore
'----------------------------------------------------------------------------
' Draw or clear the Invader's missile
CLEAR_INVADER_MISSILE:
UnPlot INVADER_MISSILE_YPOS, INVADER_MISSILE_XPOS
UnPlot INVADER_MISSILE_YPOS, INVADER_MISSILE_XPOS + 1
UnPlot INVADER_MISSILE_YPOS + 1, INVADER_MISSILE_XPOS
UnPlot INVADER_MISSILE_YPOS + 1, INVADER_MISSILE_XPOS + 1
UnPlot INVADER_MISSILE_YPOS + 2, INVADER_MISSILE_XPOS
UnPlot INVADER_MISSILE_YPOS + 2, INVADER_MISSILE_XPOS + 1
Return
DRAW_INVADER_MISSILE:
UnPlot INVADER_MISSILE_YPOS, INVADER_MISSILE_XPOS
UnPlot INVADER_MISSILE_YPOS, INVADER_MISSILE_XPOS + 1
Plot INVADER_MISSILE_YPOS + 1, INVADER_MISSILE_XPOS
Plot INVADER_MISSILE_YPOS + 1, INVADER_MISSILE_XPOS + 1
Plot INVADER_MISSILE_YPOS + 2, INVADER_MISSILE_XPOS
Plot INVADER_MISSILE_YPOS + 2, INVADER_MISSILE_XPOS + 1
Return
'----------------------------------------------------------------------------
' Draw or clear the second Invader's missile
CLEAR_INVADER_MISSILE2:
UnPlot INVADER_MISSILE2_YPOS, INVADER_MISSILE2_XPOS
UnPlot INVADER_MISSILE2_YPOS, INVADER_MISSILE2_XPOS + 1
UnPlot INVADER_MISSILE2_YPOS + 1, INVADER_MISSILE2_XPOS
UnPlot INVADER_MISSILE2_YPOS + 1, INVADER_MISSILE2_XPOS + 1
UnPlot INVADER_MISSILE2_YPOS + 2, INVADER_MISSILE2_XPOS
UnPlot INVADER_MISSILE2_YPOS + 2, INVADER_MISSILE2_XPOS + 1
Return
DRAW_INVADER_MISSILE2:
UnPlot INVADER_MISSILE2_YPOS, INVADER_MISSILE2_XPOS
UnPlot INVADER_MISSILE2_YPOS, INVADER_MISSILE2_XPOS + 1
Plot INVADER_MISSILE2_YPOS + 1, INVADER_MISSILE2_XPOS
Plot INVADER_MISSILE2_YPOS + 1, INVADER_MISSILE2_XPOS + 1
Plot INVADER_MISSILE2_YPOS + 2, INVADER_MISSILE2_XPOS
Plot INVADER_MISSILE2_YPOS + 2, INVADER_MISSILE2_XPOS + 1
Return
'----------------------------------------------------------------------------
' Re-Draw the bases
UPDATE_BASES:
Print at 6,2,2 + BASE_HITS#0,8 + BASE_HITS#1,14 + BASE_HITS#2,_
at 6,9,2 + BASE_HITS#3,8 + BASE_HITS#4,14 + BASE_HITS#5,_
at 6,15,2 + BASE_HITS#6,8 + BASE_HITS#7,14 + BASE_HITS#8
Return
'----------------------------------------------------------------------------
' Check if BASE hit by a missile
' Each base is built from three elements (characters)
' Returns with BASE_HIT set if a hit was detected
CHECK_BASE_HIT:
BASE_HIT = FALSE ' Default to no hit detected
Select BASE_XPOS_TEST
Case 12 to 17 ' Has the missile XPOS hit BASE 1, ELEMENT 0
If BASE_HITS#0 < 5 AND BASE_ENABLED#0 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#0 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#0 = FALSE ' Disable the base element
Endif
Case 18 to 23 ' Has the missile XPOS hit BASE 1, ELEMENT 1
If BASE_HITS#1 < 5 AND BASE_ENABLED#1 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#1 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#1 = FALSE ' Disable the base element
Endif
Case 24 to 29 ' Has the missile XPOS hit BASE 1, ELEMENT 2
If BASE_HITS#2 < 5 AND BASE_ENABLED#2 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#2 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#2 = FALSE ' Disable the base element
Endif
Case 54 to 59 ' Has the missile XPOS hit BASE 2, ELEMENT 3
If BASE_HITS#3 < 5 AND BASE_ENABLED#3 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#3 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#3 = FALSE ' Disable the base element
Endif
Case 60 to 65 ' Has the missile XPOS hit BASE 2, ELEMENT 4
If BASE_HITS#4 < 5 AND BASE_ENABLED#4 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#4 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#4 = FALSE ' Disable the base element
Endif
Case 66 to 71 ' Has the missile XPOS hit BASE 2, ELEMENT 5
If BASE_HITS#5 < 5 AND BASE_ENABLED#5 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#5 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#5 = FALSE ' Disable the base element
Endif
Case 90 to 95 ' Has the missile XPOS hit BASE 3, ELEMENT 6
If BASE_HITS#6 < 5 AND BASE_ENABLED#6 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#6 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#6 = FALSE ' Disable the base element
Endif
Case 96 to 101 ' Has the missile XPOS hit BASE 3, ELEMENT 7
If BASE_HITS#7 < 5 AND BASE_ENABLED#7 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#7 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#7 = FALSE ' Disable the base element
Endif
Case 102 to 107 ' Has the missile XPOS hit BASE 3, ELEMENT 8
If BASE_HITS#8 < 5 AND BASE_ENABLED#8 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#8 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#8 = FALSE ' Disable the base element
Endif
End Select
If BASE_HIT = TRUE Then Gosub UPDATE_BASES ' Update the base shapes if a hit was detected
Return
'----------------------------------------------------------------------------
' Move the invader's missile
' The missile can only be fired if the flag INVADER_MISSILE_FIRED is false,
' otherwise there is already a missile in the air
MOVE_INVADER_MISSILE:
If INVADER_MISSILE_FIRED = TRUE Then ' Don't enter the routine if the invader's missile is already flying
If TIME_TO_MOVE_INV_MISSILE = TRUE Then ' Is it time to move the invader's missile ?
Gosub DRAW_INVADER_MISSILE
Inc INVADER_MISSILE_YPOS
Endif
If INVADER_MISSILE_YPOS >= 63 OR INVADER_MISSILE_HIT = TRUE Then ' Has the invader's missile reached the bottom of the display or hit something ?
INVADER_MISSILE_FIRED = FALSE ' Yes. So signal the invader's missile is finished
Gosub CLEAR_INVADER_MISSILE ' Clear the invader's missile
INVADER_MISSILE_HIT = FALSE
Endif
Endif
Return
'----------------------------------------------------------------------------
' Move the invader's second missile
' The missile can only be fired if the flag INVADER_MISSILE2_FIRED is false,
' otherwise there is already a missile in the air
MOVE_INVADER_MISSILE2:
If INVADER_MISSILE2_FIRED = TRUE Then ' Don't enter the routine if the invader's missile is already flying
If TIME_TO_MOVE_INV_MISSILE2 = TRUE Then ' Is it time to move the invader's missile ?
Gosub DRAW_INVADER_MISSILE2
Inc INVADER_MISSILE2_YPOS
Endif
If INVADER_MISSILE2_YPOS >= 63 OR INVADER_MISSILE2_HIT = TRUE Then ' Has the invader's missile reached the bottom of the display or hit something ?
INVADER_MISSILE2_FIRED = FALSE ' Yes. So signal the invader's missile is finished
Gosub CLEAR_INVADER_MISSILE2 ' Clear the invader's missile
INVADER_MISSILE2_HIT = FALSE
Endif
Endif
Return
'----------------------------------------------------------------------------
' Fire an invader missile if possible
' The logic is: -
' Make sure a missile is not already in flight.
' Scan all the invaders...
' If the invader is enabled, then check if it is over the ship.
' If it is then enable a missile to be fired.
FIRE_INVADER_MISSILE:
If INVADER_MISSILE_FIRED = FALSE Then ' Is it OK to fire an invader missile ?
INVADER_LOOP = 0
Repeat ' Create a loop for all the invaders
If INVADER_ENABLED[INVADER_LOOP] = TRUE Then ' Is this invader enabled ?
Select INVADER_XPOS[INVADER_LOOP] + 5
Case SHIP_XPOS to SHIP_XPOS + 8 ' Is the invader over the ship ?
INVADER_MISSILE_FIRED = TRUE ' Signal that an invader's missile is in the air
INVADER_MISSILE_XPOS = INVADER_XPOS[INVADER_LOOP] + 5 ' Move missile XPOS to the middle of the invader
INVADER_MISSILE_YPOS = (INVADER_YPOS[INVADER_LOOP] * 8) + 8 ' Move missile YPOS to below the invader
End Select
Endif
Inc INVADER_LOOP
Until INVADER_LOOP > 17 ' Close the loop when all invaders have been scanned
Endif
Return
'----------------------------------------------------------------------------
' Fire an invader second missile if possible
' The logic is: -
' Make sure a missile is not already in flight.
' Scan all the invaders...
' If the invader is enabled, then check if it is over the ship.
' If it is then enable a missile to be fired.
Dim RANDOM_VALUE as Byte
FIRE_INVADER_MISSILE2:
If INVADER_MISSILE2_FIRED = FALSE Then ' Is it OK to fire an invader second missile ?
'If INVADER_MISSILE_XPOS < SHIP_XPOS Then
Select SHIP_XPOS
Case > INVADER_MISSILE_XPOS + RANDOM_VALUE , < INVADER_MISSILE_XPOS - RANDOM_VALUE
INVADER_LOOP = 0
Repeat ' Create a loop for all the invaders
If INVADER_ENABLED[INVADER_LOOP] = TRUE Then ' Is this invader enabled ?
Select INVADER_XPOS[INVADER_LOOP] + 5
Case SHIP_XPOS to SHIP_XPOS + 8 ' Is the invader over the ship ?
INVADER_MISSILE2_FIRED = TRUE ' Signal that an invader's missile is in the air
INVADER_MISSILE2_XPOS = INVADER_XPOS[INVADER_LOOP] + 5 ' Move missile XPOS to the middle of the invader
INVADER_MISSILE2_YPOS = (INVADER_YPOS[INVADER_LOOP] * 8) + 8 ' Move missile YPOS to below the invader
End Select
Endif
Inc INVADER_LOOP
Until INVADER_LOOP > 17 ' Close the loop when all invaders have been scanned
EndSelect
Endif
Return
'----------------------------------------------------------------------------
' Check if the invader's missile has hit something
' Returns with INVADER_MISSILE_HIT set if the invader's missile has hit something
CHECK_FOR_INVADER_MISSILE_HIT:
INVADER_MISSILE_HIT = FALSE ' Default to not hit
If INVADER_MISSILE_FIRED = TRUE Then ' First make sure that a missile is actually launched
' Check if the invader's missile has hit a BASE
If INVADER_MISSILE_YPOS >= 45 Then
BASE_XPOS_TEST = INVADER_MISSILE_XPOS ' Transfer the invader's missile XPOS for testing
Gosub CHECK_BASE_HIT ' Check if a base was hit
If BASE_HIT = TRUE Then
INVADER_MISSILE_HIT = TRUE ' Transfer the hit detector into the invader's missile detector
Return ' Return from the subroutine prematurely
Endif
Endif
' Check if the invader's missile has hit the ship
If INVADER_MISSILE_YPOS >= 56 Then
Select INVADER_MISSILE_XPOS
Case SHIP_XPOS - 1 To SHIP_XPOS + SHIP_WIDTH
Gosub DRAW_SHIP
INVADER_MISSILE_HIT = TRUE ' Indicate the invader's missile has hit something
SHIP_HIT = TRUE ' Indicate that it is the ship that has been hit
End Select
Endif
Endif
Return
'----------------------------------------------------------------------------
' Check if the invader's second missile has hit something
' Returns with INVADER_MISSILE2_HIT set if the invader's missile has hit something
CHECK_FOR_INVADER_MISSILE2_HIT:
INVADER_MISSILE2_HIT = FALSE ' Default to not hit
If INVADER_MISSILE2_FIRED = TRUE Then ' First make sure that a second missile is actually launched
' Check if the invader's second missile has hit a BASE
If INVADER_MISSILE2_YPOS >= 45 Then
BASE_XPOS_TEST = INVADER_MISSILE2_XPOS ' Transfer the invader's second missile XPOS for testing
Gosub CHECK_BASE_HIT ' Check if a base was hit
If BASE_HIT = TRUE Then
INVADER_MISSILE2_HIT = TRUE ' Transfer the hit detector into the invader's second missile detector
Return ' Return from the subroutine prematurely
Endif
Endif
' Check if the invader's missile has hit the ship
If INVADER_MISSILE2_YPOS >= 56 Then
Select INVADER_MISSILE2_XPOS
Case SHIP_XPOS - 1 To SHIP_XPOS + SHIP_WIDTH
Gosub DRAW_SHIP
INVADER_MISSILE2_HIT = TRUE ' Indicate the invader's second missile has hit something
SHIP_HIT = TRUE ' Indicate that it is the ship that has been hit
End Select
Endif
Endif
Return
'----------------------------------------------------------------------------
' Draw or clear the Ship's missile
CLEAR_MISSILE:
UnPlot MISSILE_YPOS, MISSILE_XPOS
UnPlot MISSILE_YPOS, MISSILE_XPOS + 1
UnPlot MISSILE_YPOS + 1, MISSILE_XPOS
UnPlot MISSILE_YPOS + 1, MISSILE_XPOS + 1
UnPlot MISSILE_YPOS + 2, MISSILE_XPOS
UnPlot MISSILE_YPOS + 2, MISSILE_XPOS + 1
Return
DRAW_MISSILE:
Plot MISSILE_YPOS, MISSILE_XPOS
Plot MISSILE_YPOS, MISSILE_XPOS + 1
Plot MISSILE_YPOS + 1, MISSILE_XPOS
Plot MISSILE_YPOS + 1, MISSILE_XPOS + 1
UnPlot MISSILE_YPOS + 2, MISSILE_XPOS
UnPlot MISSILE_YPOS + 2, MISSILE_XPOS + 1
Return
'----------------------------------------------------------------------------
' Draw the ship
DRAW_SHIP:
LCDWRITE 7,SHIP_XPOS,[$00,$E0,$F0,$F0,$F8,$FC,$F8,$F0,$F0,$E0,$00]
Return
'----------------------------------------------------------------------------
' Check if the ship's missile has hit something
' Returns with MISSILE_HIT set if the ship's missile has hit something
CHECK_FOR_MISSILE_HIT:
MISSILE_HIT = FALSE ' Default to not hit
SAUCER_HIT = FALSE ' Default to saucer not hit
If MISSILE_FIRED = TRUE Then ' First make sure a missile is actually launched
' Check if the ship's missile has hit a BASE
If MISSILE_YPOS = 53 Then
BASE_XPOS_TEST = MISSILE_XPOS ' Transfer the ship's missile XPOS for testing
Gosub CHECK_BASE_HIT ' Check if a base was hit
If BASE_HIT = TRUE Then
MISSILE_SOUND_ENABLE = 0 ' Disable the missile's sound
MISSILE_HIT = TRUE ' Transfer the hit detector into the missile detector
Return ' And return from the subroutine prematurely
Endif
Endif
' Check if the ship's missile has hit an invader's missile
If MISSILE_XPOS = INVADER_MISSILE_XPOS Then If MISSILE_YPOS = INVADER_MISSILE_YPOS Then
MISSILE_SOUND_ENABLE = 0 ' Disable the missile's sound
MISSILE_HIT = TRUE ' Indicate the ship's missile has hit a target
INVADER_MISSILE_HIT = TRUE ' Indicate the invader's missile has also been hit
Inc SCORE ' Increment the score by one
Return ' And return from the subroutine prematurely
Endif
' Check if the ship's missile has hit the saucer
If SAUCER_ENABLED = TRUE Then
If MISSILE_YPOS < 7 Then
Select MISSILE_XPOS
Case SAUCER_XPOS To SAUCER_XPOS + SAUCER_WIDTH
MISSILE_HIT = TRUE ' Indicate the ship's missile has hit a target
SAUCER_HIT = TRUE
SAUCER_SOUND_ENABLE = TRUE
SAUCER_FREQ = 30
LCDWRITE 0,SAUCER_XPOS,[$8C,$C5,$6B,$36,$0C,$20,$68,$CC,$96,$33,$69,$CC,$8 6,$02]
Delayms 10
LCDWRITE 0,SAUCER_XPOS,[$7F,$08,$08,$08,$7F,$00,$00,$41,$7F,$41,$00,$00,$0 1,$01,$7F,$01,$01] ' Display text HIT
SAUCER_FREQ = 20
Delayms 5
SAUCER_FREQ = 10
Delayms 10
SCORE = SCORE + (100 + SAUCER_XPOS) ' Add 100 + xpos to the score for hitting the saucer
SAUCER_SOUND_ENABLE = FALSE
Return
EndSelect
Endif
Endif
' Check if the ship's missile has hit an INVADER
INVADER_LOOP = 0
Repeat
If INVADER_ENABLED[INVADER_LOOP] = TRUE Then ' Only check if the invader is enabled
If INVADER_YPOS[INVADER_LOOP] = MISSILE_YPOS / 8 Then
Select MISSILE_XPOS
Case INVADER_XPOS[INVADER_LOOP] to INVADER_XPOS[INVADER_LOOP] + INVADER_WIDTH
INVADER_ENABLED[INVADER_LOOP] = FALSE
MISSILE_HIT = TRUE ' Indicate the ship's missile has hit a target
MISSILE_SOUND_ENABLE = 1
MISSILE_FREQ = 30
Select INVADER_LOOP ' Decide on the score depending on which invader is hit
Case 0 to 5 ' Top layer of invaders score 20
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$42,$61,$51,$49,$46,$00,$3E,$51,$49,$45,$3E,$00]
SCORE = SCORE + 20
Case 6 to 11 ' Middle layer of invaders score 10
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$42,$7F,$40,$00,$00,$3E,$51,$49,$45,$3E,$00]
SCORE = SCORE + 10
Case 12 to 17 ' Bottom layer of invaders score 5
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$3E,$51,$49,$45,$3E,$00, $27,$45,$45,$45,$39,$00]
SCORE = SCORE + 5
EndSelect
Delayms 10
MISSILE_FREQ = 20
Delayms 10
MISSILE_FREQ = 10
Delayms 20
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00] ' Erase the INVADER that was hit
Dec INVADERS_ENABLED ' Decrement the hits counter
If INVADERS_ENABLED = 1 Then ' Increase the speed substantially if only one invader left
INVADER_SPEED = 5
Else if INVADERS_ENABLED = 2 Then
INVADER_SPEED = 10 ' Increase the speed to fast if there are only two invaders left
Else
If INVADER_SPEED >= 3 Then ' Is the inveders speed greater than 3 ?
If INVADERS_ENABLED <= 4 Then ' Are there 4 or less invaders left ?
INVADER_SPEED = INVADER_SPEED - 3 ' Yes.. So increase their speed by a factor of three
Else
Dec INVADER_SPEED ' Otherwise.. Increase the speed of the remaining invaders
Endif
Endif
Endif
MISSILE_SOUND_ENABLE = 0 ' Disable the missile's sound
Return ' And return from the subroutine prematurely
Endselect
Endif
Endif
Inc INVADER_LOOP
Until INVADER_LOOP > 17
Endif
Return
'----------------------------------------------------------------------------
' Move the ship's missile
' The missile can only be fired if the flag MISSILE_FIRED is false,
' otherwise there is already a missile in the air
'
MOVE_MISSILE:
If MISSILE_FIRED = TRUE Then ' Don't enter the routine if the ship's missile is already flying
If TIME_TO_MOVE_SHIP_MISSILE = TRUE Then ' Is it time to move the ship's missile ?
Gosub DRAW_MISSILE
Dec MISSILE_YPOS
MISSILE_FREQ = 63 - MISSILE_YPOS
Endif
If MISSILE_YPOS = 0 OR MISSILE_HIT = TRUE Then ' Has the missile reached the top of the display or hit something ?
MISSILE_SOUND_ENABLE = 0
MISSILE_FIRED = FALSE ' Yes. So signal the missile is finished
Gosub CLEAR_MISSILE ' Clear the missile
MISSILE_YPOS = 63 - 9 ' Reset the missile to the bottom of the display
Endif
Endif
Return
'----------------------------------------------------------------------------
' Move the ship right
SHIP_RIGHT:
If SHIP_XPOS > 117 Then Return
Gosub DRAW_SHIP
Inc SHIP_XPOS
Return
'----------------------------------------------------------------------------
' Move the ship left
SHIP_LEFT:
If SHIP_XPOS = 0 Then Return
Gosub DRAW_SHIP
Dec SHIP_XPOS
Return
'----------------------------------------------------------------------------
' Move the INVADERS down a line
' And check whether they have reached the bottom of the screen
' Flag INVADERS_REACHED_BOTTOM will be set if they have
MOVE_INVADERS_DOWN:
INVADERS_REACHED_BOTTOM = FALSE ' Default to the invaders not at bottom of the screen
TEMP_LOOP = 18
Repeat
Dec TEMP_LOOP
If INVADER_ENABLED[TEMP_LOOP] = TRUE Then
LCDWRITE INVADER_YPOS[TEMP_LOOP],INVADER_XPOS[TEMP_LOOP],[$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00]
INVADER_YPOS[TEMP_LOOP] = INVADER_YPOS[TEMP_LOOP] + 1
If INVADER_YPOS[TEMP_LOOP] = 6 Then ' Have the invaders hit the bases ?
Str BASE_ENABLED = 0,0,0,0,0,0,0,0,0 ' Yes.. So disable them all
Str BASE_HITS = 5,5,5,5,5,5,5,5,5 ' And move their hit counters to past their thresholds
Endif
If INVADER_YPOS[TEMP_LOOP] >= 7 Then INVADERS_REACHED_BOTTOM = TRUE ' Set a flag if the invaders have reached the bottom
LCDWRITE INVADER_YPOS[TEMP_LOOP],INVADER_XPOS[TEMP_LOOP],[$00,$06,$0C,$9C,$EA,$36,$36,$EA,$9C,$0C,$06,$00]
Endif
Until TEMP_LOOP = 0
Inc INVADER_MISSILE_SPEED ' Slow down the invader's missile speed as they approach the bottom of the screen
If INVADER_SPEED >= 3 Then Dec INVADER_SPEED ' Increase the speed of the invaders
Return
'----------------------------------------------------------------------------
' Reset the invaders positions
' Each element of the arrays hold coordinates for the invaders
' Bit-0 of INVADER_ENABLED determines whether the invader is active or not (has been hit)
' Bit-1 of INVADER_ENABLED sets which graphic to use for the invader
' INVADER_XPOS holds the X position of the invader
' INVADER_YPOS holds the Y position of the invader
RESET_INVADERS:
INVADER_LOOP = 0
Repeat
INVADER_ENABLED[INVADER_LOOP] = TRUE ' Set all invaders to active and image 1
Select INVADER_LOOP
Case 0 to 5
INVADER_XPOS[INVADER_LOOP] = (INVADER_LOOP + 1) * 16
INVADER_YPOS[INVADER_LOOP] = 1
Case 6 to 11
INVADER_XPOS[INVADER_LOOP] = (INVADER_LOOP - 5) * 16
INVADER_YPOS[INVADER_LOOP] = 2
Case 12 to 17
INVADER_XPOS[INVADER_LOOP] = (INVADER_LOOP - 11) * 16
INVADER_YPOS[INVADER_LOOP] = 3
End Select
Inc INVADER_LOOP
Until INVADER_LOOP > 17
Return
'----------------------------------------------------------------------------
' Move the INVADERS
MOVE_INVADERS:
'If TIME_TO_MOVE_INVADERS = TRUE Then
TIME_TO_MOVE_INVADERS_DOWN = FALSE
If INVADERS_DIRECTION = FORWARD Then ' Are the invaders to move forward (right) ?
INVADER_LOOP = 0 ' Yes.. So reset the invader loop
Repeat ' Create a loop for all the invaders
If INVADER_ENABLED[INVADER_LOOP] = TRUE Then ' Is this invader enabled ?
INVADER_XPOS[INVADER_LOOP] = INVADER_XPOS[INVADER_LOOP] + 1 ' Yes.. So increment its XPOS
If INVADER_XPOS[INVADER_LOOP] >= INVADER_RIGHT_LIMIT Then ' Have we hit the right side of the screen ?
INVADERS_DIRECTION = BACKWARD ' Yes.. So indicate that we need to go backwards
SAUCER_ENABLED = TRUE
TIME_TO_MOVE_INVADERS_DOWN = TRUE ' and signal that we need to move the invaders down
Endif
Endif
Inc INVADER_LOOP
Until INVADER_LOOP > 17 ' Close the loop after all the invader elements have been scanned
Else ' Otherwise we go backwards (left)
INVADER_LOOP = 0 ' Reset the invader loop
Repeat ' Create a loop for all the invaders
If INVADER_ENABLED[INVADER_LOOP] = TRUE Then ' Is this invader enabled ?
INVADER_XPOS[INVADER_LOOP] = INVADER_XPOS[INVADER_LOOP] - 1 ' Yes.. So decrement its XPOS
If INVADER_XPOS[INVADER_LOOP] <= 1 Then ' Have we hit the left side of the screen ?
INVADERS_DIRECTION = FORWARD ' Yes.. So indicate that we need to go forwards
TIME_TO_MOVE_INVADERS_DOWN = TRUE ' and signal that we need to move the invaders down
Endif
Endif
Inc INVADER_LOOP
Until INVADER_LOOP > 17 ' Close the loop after all the invader elements have been scanned
Endif
If TIME_TO_MOVE_INVADERS_DOWN = TRUE Then Gosub MOVE_INVADERS_DOWN ' Do we need to move the invaders down ?
'Endif
' Fall through to DRAW_THE_INVADERS
'----------------------------------------------------------------------------
' Draw the invaders
' Draws one of two invader shapes depending on the contents of BIT variable INVADER_CHARACTER
' Each row of invaders is a different character
'INVADER TOP ROW character 1 $00,$18,$4C,$2E,$5B,$2F,$2F,$5B,$2E,$4C,$18,$00
'INVADER TOP ROW character 2 $00,$08,$2C,$5E,$0B,$1F,$1F,$0B,$5E,$2C,$08,$00
'INVADER MIDDLE ROW character 1 $00,$38,$0D,$3E,$5A,$1E,$1E,$5A,$3E,$0D,$38,$00
'INVADER MIDDLE ROW character 2 $00,$06,$48,$7F,$1A,$1E,$1E,$1A,$7F,$48,$06,$00
'INVADER BOTTOM ROW character 1 $00,$4C,$6E,$3A,$1B,$2F,$2F,$1B,$3A,$6E,$4C,$00
'INVADER BOTTOM ROW character 2 $00,$0C,$0E,$3A,$4B,$1F,$1F,$4B,$3A,$0E,$0C,$00
DRAW_INVADERS:
INVADER_LOOP = 0
Repeat
If INVADER_ENABLED[INVADER_LOOP] = TRUE Then
If INVADER_CHARACTER = 0 Then
INVADER_SOUND_ENABLE = 0
INVADER_FREQ = 90
Select INVADER_LOOP ' Decide on the score depending on which invader is hit
Case 0 to 5
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$18,$4C,$2E,$5B,$2F,$2F,$5B,$2E,$4C,$18,$00]
Case 6 to 11
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$38,$0D,$3E,$5A,$1E,$1E,$5A,$3E,$0D,$38,$00]
Case 12 to 17
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$4C,$6E,$3A,$1B,$2F,$2F,$1B,$3A,$6E,$4C,$00]
EndSelect
INVADER_SOUND_ENABLE = 1
Else
INVADER_SOUND_ENABLE = 0
INVADER_FREQ = 105
Select INVADER_LOOP ' Decide on the score depending on which invader is hit
Case 0 to 5
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$08,$2C,$5E,$0B,$1F,$1F,$0B,$5E,$2C,$08,$00]
Case 6 to 11
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$06,$48,$7F,$1A,$1E,$1E,$1A,$7F,$48,$06,$00]
Case 12 to 17
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$0C,$0E,$3A,$4B,$1F,$1F,$4B,$3A,$0E,$0C,$00]
EndSelect
INVADER_SOUND_ENABLE = 1
Endif
Endif
Inc INVADER_LOOP
Until INVADER_LOOP > 17
Return
'----------------------------------------------------------------------------
' Clear the saucer located at the top of the screen
CLEAR_SAUCER:
Lcdwrite 0,SAUCER_XPOS,[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
Return
'----------------------------------------------------------------------------
' Draw the saucer located at the top of the screen
DRAW_SAUCER:
Lcdwrite 0,SAUCER_XPOS,[$00,$04,$0E,$3A,$1B,$0F,$1B,$1B,$0F,$1B,$3A,$0E,$0 4,$00]
Return
'----------------------------------------------------------------------------
' Move the saucer if it is not already flying
MOVE_SAUCER:
If SAUCER_ENABLED = TRUE Then ' Don't enter the routine if the saucer is already flying
SAUCER_SOUND_ENABLE = 1 ' Enable the saucer's sound channel
If TIME_TO_MOVE_SAUCER = TRUE Then ' Is it time to move the saucer ?
Dec SAUCER_XPOS ' Move the saucer accross the screen
if SAUCER_XPOS // 2 = 0 Then
SAUCER_FREQ = 10
Else
SAUCER_FREQ = 12
Endif
Gosub DRAW_SAUCER ' Display the saucer
Endif
If SAUCER_XPOS = 0 OR SAUCER_HIT = TRUE Then ' Has the saucer reached the left of the display or been hit ?
SAUCER_ENABLED = FALSE ' Yes. So signal the sacucer is finished
Gosub CLEAR_SAUCER ' Clear the saucer
SAUCER_XPOS = 127 - SAUCER_WIDTH ' Reset the saucer to the right of the display
Print at 0,0,Dec LEVEL, " ",Dec SCORE,at 0,20,LIVES ' And display the score because it was erased by the saucer
Endif
Else
SAUCER_SOUND_ENABLE = 0 ' Disable the saucer's sound channel
Endif
Return
'----------------------------------------------------------------------------
' Determine whether a missile, ship, saucer or base should move
' governed by their individual speed controls
GOVERN_SPEEDS:
' Advance the saucers's tick (governs its speed)
Dec SAUCER_SPEED
TIME_TO_MOVE_SAUCER = FALSE
If SAUCER_SPEED = 0 Then
TIME_TO_MOVE_SAUCER = TRUE
SAUCER_SPEED = 3
Endif
' Advance the ship's tick (governs its speed)
Dec SHIP_SPEED
TIME_TO_MOVE_BASE = FALSE
If SHIP_SPEED = 0 Then
TIME_TO_MOVE_BASE = TRUE
SHIP_SPEED = 3
Endif
' Advance the invader's missile tick (governs its speed)
Inc INVADER_MISSILE_TICK
TIME_TO_MOVE_INV_MISSILE = FALSE
If INVADER_MISSILE_TICK >= INVADER_MISSILE_SPEED Then ' Set the speed for the invader's missile
TIME_TO_MOVE_INV_MISSILE = TRUE
INVADER_MISSILE_TICK = 0
Endif
' Advance the invader's second missile tick (governs its speed)
Inc INVADER_MISSILE2_TICK
TIME_TO_MOVE_INV_MISSILE2 = FALSE
If INVADER_MISSILE2_TICK >= INVADER_MISSILE2_SPEED Then ' Set the speed for the invader's second missile
TIME_TO_MOVE_INV_MISSILE2 = TRUE
INVADER_MISSILE2_TICK = 0
Endif
' Advance the ship's missile tick (governs its speed)
Dec SHIP_MISSILE_TICK
TIME_TO_MOVE_SHIP_MISSILE = FALSE
If SHIP_MISSILE_TICK = 0 Then ' Set the speed for the ship's missile
TIME_TO_MOVE_SHIP_MISSILE = TRUE
SHIP_MISSILE_TICK = 2
Endif
Return
'----------------------------------------------------------------------------
' Display the spash screen
' The subroutine re-uses some of the variables
' TEMP_LOOP, LEVEL, and INVADER_LOOP
DISPLAY_SPASH_SCREEN:
Cls
SCORE = 0
TEMP_LOOP = 0
Repeat
INVADER_LOOP = 0
Repeat
LEVEL = CREAD INVADER_SPLASH_SCREEN + SCORE
LcdWrite TEMP_LOOP,INVADER_LOOP,[LEVEL]
Inc SCORE
Inc INVADER_LOOP
Until INVADER_LOOP > 127
Inc TEMP_LOOP
Until TEMP_LOOP > 7
Return
'----------------------------------------------------------------------------
MAIN_PROGRAM_LOOP:
Gosub DISPLAY_SPASH_SCREEN
Delayms 1000
Print at 4,1,"PRESS FIRE TO START"
While FIRE_BUTTON = 1 : Wend
While FIRE_BUTTON = 0 : Wend
Delayms 50
Cls
Print at 0,7,"Scoring"
Lcdwrite 2,0,[$00,$04,$0E,$3A,$1B,$0F,$1B,$1B,$0F,$1B,$3A,$0E,$0 4,$00]
Print at 2,2," = 100+ Points"
LCDWRITE 3,0,[$00,$18,$4C,$2E,$5B,$2F,$2F,$5B,$2E,$4C,$18,$00]
Print at 3,2," = 20 Points"
LCDWRITE 4,0,[$00,$38,$0D,$3E,$5A,$1E,$1E,$5A,$3E,$0D,$38,$00]
Print at 4,2," = 10 Points"
LCDWRITE 5,0,[$00,$4C,$6E,$3A,$1B,$2F,$2F,$1B,$3A,$6E,$4C,$00]
Print at 5,2," = 5 Points"
Print at 7,1,"PRESS FIRE TO START"
While FIRE_BUTTON = 1 : Wend
While FIRE_BUTTON = 0 : Wend
Delayms 50
LEVEL = 0 ' Start at level 0
LIVES = "3" ' Set the initial lives counter to 3
SHIP_SPEED = 3
SCORE = 0
SHIP_XPOS = 64
SAUCER_SPEED = 7 ' Speed of the saucer
INVADER_SPEED = 70 ' The initial speed of the invaders
DEFAULT_INVADER_SPEED = INVADER_SPEED
TEMP_LOOP = 0
Repeat
BASE_ENABLED[TEMP_LOOP] = TRUE
BASE_HITS[TEMP_LOOP] = 0
Inc TEMP_LOOP
Until TEMP_LOOP > 8
Output PORTA ' Set all of PORTA to outputs (for sound channels)
INTERRUPT_COUNTER1 = 0
NOTE_STATUS = 0
INVADER_SOUND_COUNTER = 0
MISSILE_SOUND_COUNTER = 0
SAUCER_SOUND_COUNTER = 0
INVADER_SOUND_DURATION_COUNTER = 0
GIE = 0 ' Disable interrupts
OPTION_REG = %00000000 ' TMR0 prescaler 1:1, PORTB pullups ON
TMR0 = 0 ' Reset TMR0
INTCON = %10100000 ' Enable TMR0 Interrupt
INVADER_SOUND_ENABLE = 1 ' Enable the Invaders sound channel
INVADER_SOUND_DURATION = 20 ' Set the note duration to 20
' Main program loop starts here
' Jump to this location to implement a new sheet of invaders
NEW_SHEET:
Inc LEVEL
Cls
Gosub UPDATE_BASES ' Draw the bases (or what's left of them)
SHIP_HIT = FALSE ' Default to no hit on the ship by a missile
SAUCER_ENABLED = FALSE ' Disable the saucer
SAUCER_XPOS = 127 - SAUCER_WIDTH ' Position saucer at top tight of the screen
MISSILE_XPOS = 0
MISSILE_YPOS = 63 - 9
INVADER_MISSILE_XPOS = 0
INVADER_MISSILE_YPOS = 0
MISSILE_STATUS = 0
INVADER_MISSILE2_YPOS = 0 ' Y position of Invader's second MISSILE
INVADER_MISSILE2_XPOS = 0 ' X position of Invader's second MISSILE
TIME_TO_MOVE_INV_MISSILE2 = FALSE ' Indicate time to move the invader's second missile
INVADER_MISSILE2_FIRED = FALSE ' TRUE if Invader's second MISSILE in the air
INVADER_MISSILE2_HIT = FALSE ' Default to not hit anything
TIME_TO_MOVE_BASE = FALSE
Gosub CLEAR_INVADER_MISSILE
Gosub CLEAR_MISSILE
Gosub DRAW_SHIP ' Draw the initial ship
Dec DEFAULT_INVADER_SPEED ' Speed up the invaders every new sheet
INVADER_SPEED = DEFAULT_INVADER_SPEED ' Transfer the speed into the actual speed altering variable
Clear INVADER_TICK
Clear INVADER_MISSILE_TICK
Clear INVADER_MISSILE2_TICK
SHIP_MISSILE_TICK = 2
INVADERS_REACHED_BOTTOM = FALSE ' Default to the invaders not at the bottom of the screen
INVADER_CHARACTER = 0
INVADER_MISSILE_SPEED = 5 ' Default speed of the invader's missile
INVADER_MISSILE2_SPEED = 4
INVADERS_DIRECTION = FORWARD ' Default to the invaders moving right
INVADERS_ENABLED = 18 ' All 18 invaders are enabled
Gosub RESET_INVADERS ' Reset all the invaders positions
Gosub DRAW_INVADERS ' Place all the invaders on the screen
Print at 0,0,Dec LEVEL, " ",Dec SCORE,at 0,20,LIVES
While 1 = 1
RANDOM_VALUE = RANDOM
RANDOM_VALUE = RANDOM_VALUE & %00111000
Inc INVADER_TICK
TIME_TO_MOVE_INVADERS = FALSE
If INVADER_TICK > INVADER_SPEED Then
INVADER_TICK = 0
'TIME_TO_MOVE_INVADERS = TRUE
'If TIME_TO_MOVE_INVADERS = TRUE Then
Gosub MOVE_INVADERS
Gosub MOVE_INVADERS
INVADER_CHARACTER = ~INVADER_CHARACTER ' Use a new invader character
If INVADERS_REACHED_BOTTOM = TRUE Then GAME_OVER
Endif
Gosub MOVE_SAUCER ' Move the flying saucer (if required)
Gosub GOVERN_SPEEDS ' Check whether a piece should be moving
If L_BUTTON = 0 Then Gosub SHIP_LEFT ' Move ship left if LEFT button pressed
If R_BUTTON = 0 Then Gosub SHIP_RIGHT ' Move ship right if RIGHT button pressed
If FIRE_BUTTON = 0 Then If MISSILE_FIRED = FALSE Then ' Has the FIRE button been pressed and the ship's missile not already flying ?
SEED INVADER_SOUND_COUNTER
MISSILE_FIRED = TRUE ' Yes.. So signal we need the ship's missile FIRED
MISSILE_XPOS = SHIP_XPOS + 4 ' Place the ship's missile's xpos at the middle of the ship's shape
MISSILE_SOUND_ENABLE = 1 ' Enable the missile's sound
Endif
Gosub MOVE_MISSILE ' Move the ship's missile if OK to do so
Gosub CHECK_FOR_MISSILE_HIT ' Check if the ship's missile has hit anything
If MISSILE_HIT = TRUE OR SAUCER_HIT = TRUE Then
If BASE_HIT = FALSE Then
'Print at 0,19,Dec2 INVADERS_ENABLED," " ' Display the INVADER hits count
Print at 0,0,Dec LEVEL, " ",Dec SCORE,at 0,20,LIVES
Endif
Endif
If INVADER_CHARACTER = 1 Then
Gosub FIRE_INVADER_MISSILE ' Fire an invader missile is possible
Endif
Gosub MOVE_INVADER_MISSILE ' Move the invader's missile (if fired)
Gosub CHECK_FOR_INVADER_MISSILE_HIT ' Check if the invader's missile has hit anything
If INVADERS_ENABLED = 0 Then ' Have all the invaders been destroyed ?
INVADERS_ENABLED = 18 ' Yes.. So enable them all again
If INVADER_SPEED >= 3 Then Dec INVADER_SPEED ' Increase the speed of the invaders
Goto NEW_SHEET ' and start a new sheet
Endif
If LEVEL > 10 Then ' Add a second invader missile after level 10
If INVADER_CHARACTER = 0 then
Gosub FIRE_INVADER_MISSILE2 ' Fire an invader missile is possible
Endif
Gosub MOVE_INVADER_MISSILE2 ' Move the invader's missile (if fired)
Gosub CHECK_FOR_INVADER_MISSILE2_HIT ' Check if the invader's missile has hit anything
Endif
If SHIP_HIT = TRUE Then ' Has the ship been hit ?
SHIP_HIT = FALSE
SAUCER_SOUND_ENABLE = 1 ' Yes. So enable SAUCER sound channel
MISSILE_SOUND_ENABLE = 1 ' Enable MISSILE sound channel
MISSILE_FREQ = 70 ' Set MISSILE channel frequency to 70
SAUCER_FREQ = 90 ' Set SAUCER channel frequency to 90
LCDWRITE 7,SHIP_XPOS,[$10,$24,$AC,$F8,$F0,$E0,$F0,$F8,$AC,$24,$10] ' Draw first part of ship exploding
Delayms 40 ' Leave the graphic on the screen for 40ms
SAUCER_FREQ = 100 ' Increase the SAUCER channel's frequency
MISSILE_FREQ = 120 ' Increase the MISSILE channel's frequency
LCDWRITE 7,SHIP_XPOS,[$00,$20,$28,$F0,$A8,$C0,$E0,$F0,$28,$04,$00] ' Draw second part of ship exploding
Delayms 40 ' Leave the graphic on the screen for 40ms
SAUCER_FREQ = 150 ' Increase the SAUCER channel's frequency
MISSILE_FREQ = 135 ' Increase the MISSILE channel's frequency
LCDWRITE 7,SHIP_XPOS,[$00,$00,$30,$60,$80,$C0,$60,$30,$00,$00,$00] ' Draw third part of ship exploding
Delayms 100
LCDWRITE 7,SHIP_XPOS,[$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00] ' Clear the ship graphic
Delayms 100 ' Leave the graphic on the screen for 100ms
LIVES = LIVES - 1 ' Decrement the lives counter
MISSILE_SOUND_ENABLE = 0 ' Disable the MISSILE sound channel
SAUCER_SOUND_ENABLE = 0 ' Disable the SAUCER sound channel
If LIVES > "0" Then ' Do we have any lives left ?
LCDWRITE 7,SHIP_XPOS,[$00,$E0,$F0,$F0,$F8,$FC,$F8,$F0,$F0,$E0,$00] ' Yes. So Re-draw the ship and carry on
Print at 0,20,LIVES ' Update the Display for the amount of lives
Else ' Otherwise, we don't have any lives left
Goto GAME_OVER ' So game over
Endif
Endif
Delayms 6 ' Main game speed setting
Wend
'--------------------------------------------------------------------
' Explode the ship when the game is over
GAME_OVER:
Print at 0,0,Dec LEVEL, " ",Dec SCORE,at 0,20,LIVES
SAUCER_SOUND_ENABLE = TRUE ' Enable SAUCER sound channel
MISSILE_SOUND_ENABLE = TRUE ' Enable MISSILE sound channel
MISSILE_FREQ = 70 ' Set MISSILE channel frequency to 70
SAUCER_FREQ = 90 ' Set SAUCER channel frequency to 90
TEMP_LOOP = 1
Repeat
MISSILE_FREQ = MISSILE_FREQ - TEMP_LOOP
SAUCER_FREQ = SAUCER_FREQ - TEMP_LOOP
Delayms 10 + TEMP_LOOP
Circle 1,SHIP_XPOS + 5,63,TEMP_LOOP
If TEMP_LOOP > 10 Then
Circle 0,SHIP_XPOS + 5,63,TEMP_LOOP - 10
Endif
TEMP_LOOP = TEMP_LOOP + 2
Until TEMP_LOOP > 24
SAUCER_SOUND_ENABLE = FALSE ' Disable SAUCER sound channel
MISSILE_SOUND_ENABLE = FALSE ' Disable MISSILE sound channel
TEMP_LOOP = 1
Repeat
Circle 0,SHIP_XPOS + 5,63,TEMP_LOOP
TEMP_LOOP = TEMP_LOOP + 2
Until TEMP_LOOP > 24
'Cls
Print at 3,6,INVERSE 1,"GAME OVER", INVERSE 0
Delayms 500
Print at 4,1,"PRESS FIRE TO START"
While FIRE_BUTTON = 1 : Wend
Delayms 50
While FIRE_BUTTON = 0 : Wend
Delayms 50
Goto MAIN_PROGRAM_LOOP
'--------------------------------------------------------------------
' Font CDATA table for space invaders game
FONT:- CData $00,$00,$00,$00,$00,$00 'Graphic Character 0
CData $FF,$FF,$FF,$FF,$FF,$FF 'Graphic Character 1
CData $E0,$F0,$F8,$FC,$FC,$FE ' Left side of base complete (Character 2)
CData $C0,$B0,$B0,$70,$EC,$F8 ' Left side of base after hit 1 (Character 3)
CData $C0,$A0,$B0,$70,$AC,$28 ' Left side of base after hit 2 (Character 4)
CData $40,$A0,$B0,$70,$A0,$20 ' Left side of base after hit 3 (Character 5)
CData $40,$80,$80,$40,$A0,$20 ' Left side of base after hit 4 (Character 6)
CData $00,$00,$00,$00,$00,$00 ' Left side of base after hit 5 (Character 7)
CData $FE,$FE,$FE,$FE,$FE,$FE ' Middle of base complete (Character 8)
CData $FE,$DE,$EC,$F0,$F8,$FE ' Middle of base after hit 1 (Character 9)
CData $F8,$DE,$E4,$F0,$D8,$9E ' Middle of base after hit 2 (Character 10)
CData $B8,$DE,$A4,$B0,$48,$B4 ' Middle of base after hit 3 (Character 11)
CData $34,$58,$A4,$B8,$48,$34 ' Middle of base after hit 4 (Character 12)
CData $00,$00,$00,$00,$00,$00 ' Middle of base after hit 5 (Character 13)
CData $FE,$FC,$FC,$F8,$F0,$E0 ' Right side of base complete (Character 14)
CData $C0,$B0,$B0,$70,$EC,$F8 ' Right side of base after hit 1 (Character 15)
CData $C0,$A0,$B0,$70,$AC,$28 ' Right side of base after hit 2 (Character 16)
CData $40,$A0,$B0,$70,$A0,$20 ' Right side of base after hit 3 (Character 17)
CData $40,$80,$80,$40,$A0,$20 ' Right side of base after hit 4 (Character 18)
CData $00,$00,$00,$00,$00,$00 ' Right side of base after hit 5 (Character 19)
CData $FF,$00,$00,$00,$00,$00 'Graphic character 20
CData $00,$00,$00,$00,$00,$FF 'Graphic character 21
CData $FF,$01,$01,$01,$01,$01 'Graphic character 22
CData $01,$01,$01,$01,$01,$FF 'Graphic character 23
CData $FF,$80,$80,$80,$80,$80 'Graphic character 24
CData $80,$80,$80,$80,$80,$FF 'Graphic character 25
CData $00,$00,$00,$00,$F0,$F0 'User defined character 26
CData $00,$00,$00,$00,$0F,$0F 'User defined character 27
CData $00,$00,$00,$00,$00,$00 'User defined character 28
CData $00,$00,$00,$00,$00,$00 'User defined character 29
CData $00,$00,$00,$00,$00,$00 'User defined character 30
CData $00,$00,$00,$00,$00,$00 'User defined character 31
CData $00,$00,$00,$00,$00,$00 '32 - - 20
CData $00,$00,$4F,$00,$00,$00 '33 - ! - 21
CData $00,$07,$00,$07,$00,$00 '34 - " - 22
CData $14,$7F,$14,$7F,$14,$00 '35 - # - 23
CData $24,$2A,$7F,$2A,$12,$00 '36 - $ - 24
CData $23,$13,$08,$64,$62,$00 '37 - % - 25
CData $36,$49,$55,$22,$50,$00 '38 - & - 26
CData $00,$05,$03,$00,$00,$00 '39 - ' - 27
CData $1C,$22,$41,$00,$00,$00 '40 - ( - 28
CData $00,$00,$41,$22,$1C,$00 '41 - ) - 29
CData $14,$08,$3E,$08,$14,$00 '42 - * - 2A
CData $08,$08,$3E,$08,$08,$00 '43 - + - 2B
CData $00,$50,$30,$00,$00,$00 '44 - , - 2C
CData $08,$08,$08,$08,$08,$00 '45 - - - 2D
CData $00,$60,$60,$00,$00,$00 '46 - . - 2E
CData $20,$10,$08,$04,$02,$00 '47 - / - 2F
CData $3E,$51,$49,$45,$3E,$00 '48 - 0 - 30
CData $00,$42,$7F,$40,$00,$00 '49 - 1 - 31
CData $42,$61,$51,$49,$46,$00 '50 - 2 - 32
CData $21,$41,$45,$4B,$31,$00 '51 - 3 - 33
CData $18,$14,$12,$7F,$10,$00 '52 - 4 - 34
CData $27,$45,$45,$45,$39,$00 '53 - 5 - 35
CData $3C,$4A,$49,$49,$30,$00 '54 - 6 - 36
CData $01,$71,$09,$05,$03,$00 '55 - 7 - 37
CData $36,$49,$49,$49,$36,$00 '56 - 8 - 38
CData $06,$49,$49,$49,$3E,$00 '57 - 9 - 39
CData $00,$36,$36,$00,$00,$00 '58 - : - 3A
CData $00,$56,$36,$00,$00,$00 '59 - ; - 3B
CData $08,$14,$22,$41,$00,$00 '60 - < - 3C
CData $14,$14,$14,$14,$14,$00 '61 - = - 3D
CData $00,$41,$22,$14,$08,$00 '62 - > - 3E
CData $02,$01,$51,$09,$06,$00 '63 - ? - 3F
CData $32,$49,$79,$41,$3E,$00 '64 - @ - 40
CData $7E,$11,$11,$11,$7E,$00 '65 - A - 41
CData $7F,$49,$49,$49,$36,$00 '66 - B - 42
CData $3E,$41,$41,$41,$22,$00 '67 - C - 43
CData $7F,$41,$41,$22,$1C,$00 '68 - D - 44
CData $7F,$49,$49,$49,$41,$00 '69 - E - 45
CData $7F,$09,$09,$09,$01,$00 '70 - F - 46
CData $3E,$41,$49,$49,$7A,$00 '71 - G - 47
CData $7F,$08,$08,$08,$7F,$00 '72 - H - 48
CData $00,$41,$7F,$41,$00,$00 '73 - I - 49
CData $20,$40,$41,$3F,$01,$00 '74 - J - 4A
CData $7F,$08,$14,$22,$41,$00 '75 - K - 4B
CData $7F,$40,$40,$40,$40,$00 '76 - L - 4C
CData $7F,$02,$0C,$02,$7F,$00 '77 - M - 4D
CData $7F,$04,$08,$10,$7F,$00 '78 - N - 4E
CData $3E,$41,$41,$41,$3E,$00 '79 - O - 4F
CData $7F,$09,$09,$09,$06,$00 '80 - P - 50
CData $3E,$41,$51,$21,$5E,$00 '81 - Q - 51
CData $7F,$09,$19,$29,$46,$00 '82 - R - 52
CData $46,$49,$49,$49,$31,$00 '83 - S - 53
CData $01,$01,$7F,$01,$01,$00 '84 - T - 54
CData $3F,$40,$40,$40,$3F,$00 '85 - U - 55
CData $1F,$20,$40,$20,$1F,$00 '86 - V - 56
CData $3F,$40,$38,$40,$3F,$00 '87 - W - 57
CData $63,$14,$08,$14,$63,$00 '88 - X - 58
CData $07,$08,$70,$08,$07,$00 '89 - Y - 59
CData $61,$51,$49,$45,$43,$00 '90 - Z - 5A
CData $7F,$41,$41,$00,$00,$00 '91 - [ - 5B
CData $02,$04,$08,$10,$20,$00 '92 - \ - 5C
CData $00,$00,$41,$41,$7F,$00 '93 - ] - 5D
CData $04,$02,$01,$02,$04,$00 '94 - ^ - 5E
CData $40,$40,$40,$40,$40,$00 '95 - _ - 5F
CData $00,$01,$02,$04,$00,$00 '96 - ` - 60
CData $20,$54,$54,$54,$78,$00 '97 - a - 61
CData $7F,$48,$44,$44,$38,$00 '98 - b - 62
CData $38,$44,$44,$44,$20,$00 '99 - c - 63
CData $38,$44,$44,$48,$7F,$00 '100 d - 64
CData $38,$54,$54,$54,$18,$00 '101 e - 65
CData $08,$7E,$09,$01,$02,$00 '102 f - 66
CData $0C,$52,$52,$52,$3E,$00 '103 g - 67
CData $7F,$08,$04,$04,$78,$00 '104 h - 68
CData $00,$44,$7D,$40,$00,$00 '105 i - 69
CData $00,$20,$40,$44,$3D,$00 '106 j - 6A
CData $7F,$10,$28,$44,$00,$00 '107 k - 6B
CData $00,$41,$7F,$40,$00,$00 '108 l - 6C
CData $7C,$04,$18,$04,$78,$00 '109 m - 6D
CData $7C,$08,$04,$04,$78,$00 '110 n - 6E
CData $38,$44,$44,$44,$38,$00 '111 o - 6F
CData $7C,$14,$14,$14,$08,$00 '112 p - 70
CData $08,$14,$14,$18,$7C,$00 '113 q - 71
CData $7C,$08,$04,$04,$08,$00 '114 r - 72
CData $48,$54,$54,$54,$20,$00 '115 s - 73
CData $04,$3F,$44,$40,$20,$00 '116 t - 74
CData $3C,$40,$40,$20,$7C,$00 '117 u - 75
CData $1C,$20,$40,$20,$1C,$00 '118 v - 76
CData $3C,$40,$30,$40,$3C,$00 '119 w - 77
CData $44,$28,$10,$28,$44,$00 '120 x - 78
CData $0C,$50,$50,$50,$3C,$00 '121 y - 79
CData $44,$64,$54,$4C,$44,$00 '122 z - 7A
CData $08,$36,$41,$00,$00,$00 '123 { - 7B
CData $00,$00,$7F,$00,$00,$00 '124 | - 7C
CData $00,$00,$41,$36,$08,$00 '125 } - 7D
CData $00,$08,$04,$08,$04,$00 '126 ~ - 7E
'--------------------------------------------------------------------
INVADER_SPLASH_SCREEN:
CDATA $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$40,$70,$78,_
$7C,$7C,$7C,$7C,$7C,$FC,$F8,$F0,$E0,$C0,$C0,$7C,$7 C,$7C,$7C,$7C,_
$7C,$7C,$7C,$7C,$7C,$7C,$F8,$F0,$E0,$C0,$00,$00,$8 0,$7C,$7C,$7C,_
$7C,$7C,$7C,$7C,$7C,$70,$80,$00,$00,$00,$80,$C0,$F 0,$F8,$3E,$3E,_
$3E,$3E,$3E,$3E,$3E,$3E,$3E,$7C,$F8,$E0,$C0,$FE,$F E,$3E,$3E,$3E,_
$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$20,$A0,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$60,$F0,$0C,$06,$0 6,$06,$06,$86,_
$86,$86,$06,$06,$06,$0C,$19,$F3,$C7,$3F,$FF,$02,$0 2,$02,$02,$02,_
$82,$82,$82,$82,$02,$06,$0C,$19,$33,$E7,$F8,$00,$F F,$02,$02,$02,_
$02,$02,$02,$02,$02,$06,$FF,$00,$00,$FE,$FF,$F3,$7 1,$08,$0C,$06,_
$02,$02,$82,$82,$82,$02,$02,$02,$07,$0F,$FF,$3F,$C 0,$FC,$1E,$02,_
$02,$02,$03,$C3,$C3,$C3,$C3,$C3,$C3,$43,$73,$1F,$0 3,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$03,$3C,$E0,$8 0,$00,$00,$03,_
$1E,$61,$5E,$58,$58,$58,$58,$99,$BF,$40,$03,$FF,$C 0,$00,$00,$00,_
$01,$FF,$83,$FF,$00,$00,$00,$00,$00,$FF,$07,$FE,$0 F,$00,$00,$00,_
$F8,$7F,$E0,$00,$00,$00,$0F,$FC,$00,$FF,$01,$FF,$0 0,$00,$00,$00,_
$00,$FE,$1F,$0C,$0F,$08,$08,$08,$F8,$7E,$07,$FC,$1 F,$03,$00,$00,_
$00,$00,$0F,$0F,$0D,$E8,$38,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 1,$63,$E6,$2C,_
$28,$28,$68,$E8,$98,$F0,$00,$01,$01,$07,$FE,$83,$7 F,$F0,$00,$00,_
$00,$01,$E1,$21,$60,$30,$30,$0C,$06,$01,$00,$FF,$0 0,$00,$00,$00,_
$8F,$8C,$8F,$00,$00,$00,$00,$3F,$F8,$3F,$FE,$07,$0 0,$00,$00,$80,_
$FF,$C1,$FE,$0E,$02,$02,$82,$FB,$1F,$E0,$FF,$03,$0 0,$00,$00,$F0,_
$BE,$83,$83,$E3,$82,$83,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$C0,$40,$40,$5C,$7C,$7C,$FC,$F C,$F0,$40,$4C,_
$7C,$7C,$7C,$FC,$FC,$F8,$20,$00,$0C,$3C,$3C,$7C,$F C,$FC,$F3,$06,_
$0C,$18,$30,$71,$F1,$F1,$F1,$D0,$18,$0C,$3F,$3D,$3 C,$FF,$FC,$F8,_
$18,$18,$DF,$1E,$3C,$3C,$3C,$3C,$3C,$3C,$3F,$F8,$0 8,$08,$08,$0E,_
$0F,$3C,$3F,$3F,$38,$38,$38,$38,$3F,$3E,$7D,$F3,$E C,$08,$F8,$F8,_
$78,$38,$38,$38,$3C,$3F,$3F,$3E,$3E,$3F,$38,$38,$3 8,$E8,$88,$F8,_
$78,$38,$38,$3C,$3F,$3E,$3E,$38,$30,$20,$40,$80,$C 0,$F0,$F8,$FC,_
$FE,$7E,$3E,$1E,$1E,$1E,$1E,$1E,$1C,$10,$00,$40,$8 0,$00,$00,$00,_
$00,$06,$0E,$36,$C6,$82,$02,$06,$1C,$30,$C6,$8F,$3 B,$E3,$82,$02,_
$06,$0C,$30,$6E,$FB,$C3,$03,$02,$02,$02,$1E,$73,$9 F,$73,$C3,$83,_
$03,$07,$1C,$70,$C1,$07,$7F,$C3,$03,$03,$03,$03,$7 F,$C0,$FF,$FF,_
$FF,$FF,$03,$03,$03,$03,$03,$03,$03,$07,$3E,$C3,$7 F,$E0,$00,$00,_
$FF,$03,$03,$01,$E1,$E1,$21,$E1,$01,$01,$03,$06,$8 F,$F8,$FF,$3F,_
$FC,$07,$01,$01,$01,$01,$E1,$E1,$A1,$A1,$A1,$21,$E 1,$F1,$3F,$E3,_
$3C,$07,$01,$01,$01,$C1,$61,$E1,$61,$01,$01,$01,$0 1,$C7,$7F,$99,_
$70,$3C,$06,$02,$03,$C1,$31,$B1,$71,$31,$01,$01,$8 1,$C1,$76,$18,_
$00,$00,$00,$00,$00,$01,$06,$0C,$30,$40,$80,$01,$0 6,$0C,$31,$C6,_
$9C,$70,$C0,$00,$00,$01,$07,$00,$80,$00,$00,$00,$0 7,$1E,$F0,$83,_
$0E,$38,$E0,$80,$00,$07,$0C,$7F,$80,$00,$00,$00,$0 0,$FF,$07,$FF,_
$FF,$FF,$00,$00,$00,$00,$FF,$E0,$00,$00,$00,$07,$F 8,$8F,$FC,$80,_
$FF,$00,$00,$00,$FF,$07,$00,$FF,$00,$00,$00,$80,$F F,$FF,$8F,$7E,_
$03,$00,$00,$00,$00,$E4,$A7,$A6,$A6,$26,$FE,$7E,$C F,$F9,$0F,$01,_
$00,$00,$C0,$C8,$CE,$09,$07,$01,$30,$F0,$68,$2C,$2 7,$39,$3E,$C3,_
$40,$40,$C8,$4E,$0B,$08,$0A,$9B,$F2,$03,$03,$03,$0 1,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$02,$0 C,$30,$60,$C0,_
$C1,$C6,$5D,$F7,$CC,$30,$E0,$C0,$C0,$47,$5E,$6C,$3 0,$60,$40,$43,_
$5E,$74,$04,$05,$06,$18,$70,$40,$40,$40,$40,$40,$4 0,$47,$7E,$07,_
$01,$7F,$40,$40,$40,$40,$79,$09,$09,$70,$40,$40,$4 0,$4F,$74,$01,_
$7F,$40,$40,$40,$47,$44,$46,$41,$40,$20,$10,$0F,$0 1,$43,$7F,$40,_
$40,$40,$40,$40,$4F,$48,$48,$48,$78,$08,$70,$5E,$4 3,$40,$40,$60,_
$38,$47,$7B,$47,$41,$40,$70,$1C,$07,$03,$3E,$61,$4 1,$61,$69,$6F,_
$6D,$66,$61,$30,$10,$1C,$06,$03,$00,$00,$00,$00,$0 0,$00,$00,$00
' For version 2.1 of the PROTON+ BASIC Compiler
' Written by Les Johnson 2003.
'
' This version uses the LCDWRITE and PLOT commands to produce the graphics
' Which allows smooth movements on a pixel by pixel basis
'
' Use an 8MHz crystal
'
' BUTTON CONNECTIONS
' LEFT Button connects to PORTB.0
' RIGHT Button connects to PORTB.1
' FIRE Button connects to PORTB.2
'
' SOUND CHANNEL CONNECTIONS
' Each channel is output from PORTA.0,1,2
' Channel 1. PORTA.0 is the INVADER noise
' Channel 2. PORTA.1 is the MISSILE noise
' Channel 3. PORTA.2 is the SAUCER noise
' Each pin should have a current limiting resistor in order to stop pin to pin shorts.
'
' 1uF
' 220 +| |-
' PORTA.0 --/\/\/\----| |--- To SPEAKER
' | | |
' 330 |
' PORTA.1 --/\/\/\--|
' |
' 330 |
' PORTA.2 --/\/\/\--|
'
'
' * Revision 1.0 10 September 2003
'
' Ship moving smoothly and missile working correctly
'
' * Revision 1.1 10 September 2003
'
' Invaders moving left to right and down (got a problem with alignment when moving down)
' Invaders become faster as they move down
' Invader erased when missile hits, and hit counter incremented
' Bases require five hits per section before they dissapear
' There are 9 sections, three in each base
' A new sheet of invaders is created when all of them are hit
' The new sheet is slightly faster than the previous one
'
' * Revision 1.2 11 September 2003
'
' Invaders now move down the screen without alignment problems
' Started placing subroutines to enable the invaders to fire back at the ship
' Placed the base hit check as a subroutine so that the invader's missile can also
' be checked for a base hit.
' Invaders can now fire back, but cannot detect any hits yet.
' Both the ship's and the invader's missiles are slowed down but still need some work.
'
' * Revision 1.3 12 September 2003
'
' Both the ship's and the invaders missiles have independant speed controls
' Invader's missile now detect whether it has hit a base, and alters the base accordingly
' Still a problem with the invader's missile hitting the base, sometimes destroys it with one blow
' Game now detects whether the invaders have reached the bottom of the screen. In which case, GAME OVER
' If the invaders reach the bases, then the bases are disabled
' Invaders now have animated characters
' Bases also have animated characters that destroy with every hit with a missile
' The ship now only moves one pixel at a time instead of two. This slow the ship to a reasonable speed
' The invaders speed up whenever one is hit, and also speed up by a factor of 3 when there are 4 or less invaders left
' Invaders also speed up whenever they move down the screen
' Added simple sound effects when invaders move. This will be altered later.
'
' * Revision 1.4 13 September 2003
'
' Flying saucer now moves right to left at the top of the screen
' Missile to missile collisions are now detected
'
' * Revision 1.5 14 September 2003
'
' Missiles are now implemented using the PLOT command for smooth movement
' As the invaders move down the screen their missile speed slows down slightly
' Game now detects a hit on the flying saucer at the top of the screen
' There is still a problem with the invaders and the ship hitting the bases
' The base counter is decremented too quickly, or destroyed with a single hit
'
' * Revision 1.6 18 September 2003
'
' Added scoring for invaders and saucer
' Invaders score 20 points for top row, 10 points for middle row, and 5 points for bottom row
' Saucer scores 100 points if hit
' A small animation of the points scored is also included if the saucer or invaders are hit.
' Added simple sound effects for invaders, saucer and missile shot.
'
' * Revision 1.7 27 September 2003
'
' Added second missile for space invaders, but still requires some work
' because the spread of missiles is uneven.
'
' * Revision 1.8 28 September 2003
'
' Replaced sound using the SOUND command with interrupt driven sounds
' There are three independant sound channels from PORTA0,1,2
' Each is capable of producing a different frequency, and channel one (INVADER channel) also has a duration.
' With the interrupt driven sound, I have had to increase the crystal to 8MHz.
' Each layer of invader now has a different invader sprite, each consisting of two characters.
' Created new user defined shape for saucer and ship.
' Saucer now scores 100+ points if hit. More points gained the closer to the right hand side of the screen.
' Added levels to the game. After level 10 the invaders start firing two missiles.
'
' * Revision 1.9 01 October 2003
'
' Invader to Ship missile collision detection is now implemented
' Each time the ship is hit a life is decremented.
' After three lives the game is over.
' Added a splash screen when the game first starts
'
' * Revision 2 04 October 2003
'
' Score increases by one if a missile hits a missile
' If there are only 1 or 2 invaders left on the screen their speed increases dramatically
' When all the ship's lives are lost, a large circular explosion occurs.
'
'
'
' See if thare are any improvements you can make, and report them on the Forum!
'
Include "PROTON_G8.INT" ' Game created on the PROTON board
' Set up some Variables
' Interrupt driven sound channel variables
Dim NOTE_STATUS as Byte SYSTEM
Dim INVADER_SOUND_ENABLE as NOTE_STATUS.0
Dim MISSILE_SOUND_ENABLE as NOTE_STATUS.1
Dim SAUCER_SOUND_ENABLE as NOTE_STATUS.2
Dim INTERNAL_INVADER_SOUND_ENABLE as NOTE_STATUS.4
Dim INTERRUPT_COUNTER1 as Byte SYSTEM
Dim INVADER_SOUND_COUNTER as Byte SYSTEM
Dim INVADER_FREQ as Byte SYSTEM
Dim INVADER_SOUND_DURATION as Byte SYSTEM
Dim INVADER_SOUND_DURATION_COUNTER as Byte SYSTEM
Dim MISSILE_SOUND_COUNTER as Byte SYSTEM
Dim MISSILE_FREQ as Byte SYSTEM
Dim SAUCER_SOUND_COUNTER as Byte SYSTEM
Dim SAUCER_FREQ as Byte SYSTEM
' Space invader variables
Dim BASE_ENABLED[9] as Byte ' Whether or not the section of the BASE is enabled
Dim BASE_HITS[9] as Byte ' Holds the amount of hits each part of the bases has had
Dim INVADER_XPOS[18] as Byte' at 400 ' Array to hold the space invader's X position
Dim INVADER_YPOS[18] as Byte' at 418 ' Array to hold the space invader's Y position
Dim INVADER_ENABLED[18] as Byte' at 436 ' Array to hold the space invader' config. i.e. hit or active
Dim SHIP_XPOS as Byte ' X position of BASE ship
Dim MISSILE_YPOS as Byte ' Y position of Ship's MISSILE
Dim MISSILE_XPOS as Byte ' X position of Ship's MISSILE
Dim MISSILE_STATUS as Byte SYSTEM
Dim MISSILE_FIRED as MISSILE_STATUS.0 ' TRUE if Ship's MISSILE in the air
Dim MISSILE_HIT as MISSILE_STATUS.1 ' Set if Ship's missile has hit something
Dim TIME_TO_MOVE_INVADERS as MISSILE_STATUS.7 ' Indicate time to move the invaders
Dim BASE_HIT as MISSILE_STATUS.2 ' Indicates whether a BASE has been hit by a missile
Dim TIME_TO_MOVE_SHIP_MISSILE as MISSILE_STATUS.3 ' Indicate time to move the ship's missile
Dim TIME_TO_MOVE_BASE as Bit
Dim SHIP_SPEED as Byte
Dim INVADER_TICK as Byte ' Constant tick within program
Dim INVADER_LOOP as Byte SYSTEM ' Scans the invader arrays
Dim INVADER_MISSILE_TICK as Byte
Dim SHIP_MISSILE_TICK as Byte
Dim TEMP_LOOP as Byte
Dim INVADERS_DIRECTION as Bit
Dim INVADERS_ENABLED as Byte ' Count the INVADERS enabled
Dim INVADER_SPEED as Byte ' The speed of the invaders
Dim BASE_XPOS_TEST as Byte ' Used for detecting a missile hit on a BASE
Dim SHIP_HIT as Bit ' TRUE if ship hit by missile
Dim INVADER_MISSILE_YPOS as Byte ' Y position of Invader's MISSILE
Dim INVADER_MISSILE_XPOS as Byte ' X position of Invader's MISSILE
Dim TIME_TO_MOVE_INV_MISSILE as MISSILE_STATUS.4 ' Indicate time to move the invader's missile
Dim INVADER_MISSILE_FIRED as MISSILE_STATUS.5 ' TRUE if Invader's MISSILE in the air
Dim INVADER_MISSILE_HIT as MISSILE_STATUS.6 ' Set if Invader's missile has hit something
Dim TIME_TO_MOVE_INVADERS_DOWN as Bit ' Signal that the invaders need to move down
Dim INVADERS_REACHED_BOTTOM as Bit ' Set if the invaders reach the botton of the screen
Dim INVADER_MISSILE_SPEED as Byte ' The speed of the invader's missile. This slows down as invader near the bottom of the screen
Dim DEFAULT_INVADER_SPEED as Byte ' Saves the initial speed of the invaders
Dim INVADER_CHARACTER as Bit ' Determines the character to use for the invader
Dim INVADER_MISSILE2_TICK as Byte
Dim INVADER_MISSILE2_YPOS as Byte ' Y position of Invader's second MISSILE
Dim INVADER_MISSILE2_XPOS as Byte ' X position of Invader's second MISSILE
Dim TIME_TO_MOVE_INV_MISSILE2 as Bit ' Indicate time to move the invader's second missile
Dim INVADER_MISSILE2_FIRED as Bit ' TRUE if Invader's second MISSILE in the air
Dim INVADER_MISSILE2_HIT as Bit ' Set if Invader's second missile has hit something
Dim INVADER_MISSILE2_SPEED as Byte ' The speed of the invader's second missile. This slows down as invader near the bottom of the screen
Dim SAUCER_XPOS as Byte
Dim SAUCER_HIT as Bit
Dim TIME_TO_MOVE_SAUCER as Bit
Dim SAUCER_SPEED as Byte
Dim SAUCER_ENABLED as Bit
Dim SCORE as Dword ' Holds the games score
Dim LEVEL as Word ' Game level
Dim LIVES as Byte ' Amount of lives left for the base
' Define some constants and alias's
Symbol L_BUTTON = PORTB.0
Symbol R_BUTTON = PORTB.1
Symbol FIRE_BUTTON = PORTB.2
Symbol SPEAKER = PORTB.3
Symbol SHIP_WIDTH = 9 ' The width of the ship in pixels. This does not include the two blanks
Symbol INVADER_WIDTH = 10 ' The width of the invaders. minus the two outside blanks
Symbol INVADER_RIGHT_LIMIT = 127 - INVADER_WIDTH ' The right most limit for the invaders before they need to move down
Symbol SAUCER_WIDTH = 14
Symbol TRUE = 1
Symbol FALSE = 0
Symbol FORWARD = 1
Symbol BACKWARD = 0
Symbol T0IF INTCON.2 ' Timer0 Overflow Interrupt Flag
Symbol GIE INTCON.7 ' Global Interrupt Enable
ON_INTERRUPT Goto NOTE_INT
'----------------------------------------------------------------------------
Input L_BUTTON
Input R_BUTTON
Input FIRE_BUTTON
Delayms 200 ' Wait for the PICŪ micro to stabilise
PORTB_PULLUPS = ON
Cls ' Clear the LCD
Goto MAIN_PROGRAM_LOOP ' Jump over any subroutines
'----[NOTE GENERATING INTERRUPT HANDLER]---------------------------------------------------
NOTE_INT:
TMR0 = 200
Incf INVADER_SOUND_COUNTER,F
Incf MISSILE_SOUND_COUNTER,F
Incf SAUCER_SOUND_COUNTER,F
Incf INTERRUPT_COUNTER1,F
Btfss INTERRUPT_COUNTER1,6 ' If INTERRUPT_COUNT.6 = 1
Jump INVADER_SOUND_LOOP
Clrf INTERRUPT_COUNTER1 ' INTERRUPT_COUNT = 0
Bcf INTERNAL_INVADER_SOUND_ENABLE ' INTERNAL_INVADER_SOUND_ENABLE = 0
Movfw INVADER_SOUND_DURATION_COUNTER ' If((INVADER_SOUND_DURATION_COUNTER <= INVADER_SOUND_DURATION) && (INVADER_SOUND_ENABLE == 1))
Subwf INVADER_SOUND_DURATION,W
Btfss STATUS,C
Jump FINISH_NOTE1
Btfss INVADER_SOUND_ENABLE
Jump FINISH_NOTE1
Incf INVADER_SOUND_DURATION_COUNTER,F ' INVADER_SOUND_DURATION_COUNTER++
Bsf INTERNAL_INVADER_SOUND_ENABLE ' INTERNAL_INVADER_SOUND_ENABLE = 1
Jump INVADER_SOUND_LOOP ' Otherwise
FINISH_NOTE1:
BCF INVADER_SOUND_ENABLE ' INVADER_SOUND_ENABLE = 0
CLRF INVADER_SOUND_DURATION_COUNTER ' INVADER_SOUND_DURATION_COUNTER = 0
INVADER_SOUND_LOOP:
Movfw INVADER_FREQ ' If INVADER_SOUND_COUNTER >= INVADER_FREQ
Subwf INVADER_SOUND_COUNTER,W
Btfss STATUS,C
Jump MISSILE_SOUND_LOOP
Clrw
Btfsc INTERNAL_INVADER_SOUND_ENABLE
Movlw 1 ' Set for tone generation on PORTA.0
Xorwf PORTA,F ' PORTA = PORTA ^ 1
Clrf INVADER_SOUND_COUNTER ' INVADER_SOUND_COUNTER = 0
MISSILE_SOUND_LOOP:
Movfw MISSILE_FREQ ' If MISSILE_SOUND_COUNTER >= MISSILE_FREQ
Subwf MISSILE_SOUND_COUNTER,W
Btfss STATUS,C
Jump SAUCER_SOUND_LOOP
Clrw
Btfsc MISSILE_SOUND_ENABLE
Movlw 2 ' Set for tone generation on PORTA.1
Xorwf PORTA,F ' PORTA = PORTA ^ 2
Clrf MISSILE_SOUND_COUNTER ' MISSILE_SOUND_COUNTER = 0
SAUCER_SOUND_LOOP:
Movfw SAUCER_FREQ ' If SAUCER_SOUND_COUNTER >= SAUCER_FREQ
Subwf SAUCER_SOUND_COUNTER,W
Btfss STATUS,C
Jump EXIT_INTERRUPT
Clrw
Btfsc SAUCER_SOUND_ENABLE
Movlw 4 ' Set for tone generation on PORTA.2
Xorwf PORTA,F ' PORTA = PORTA ^ 4
Clrf SAUCER_SOUND_COUNTER ' SAUCER_SOUND_COUNTER = 0
EXIT_INTERRUPT:
T0IF = 0
Context Restore
'----------------------------------------------------------------------------
' Draw or clear the Invader's missile
CLEAR_INVADER_MISSILE:
UnPlot INVADER_MISSILE_YPOS, INVADER_MISSILE_XPOS
UnPlot INVADER_MISSILE_YPOS, INVADER_MISSILE_XPOS + 1
UnPlot INVADER_MISSILE_YPOS + 1, INVADER_MISSILE_XPOS
UnPlot INVADER_MISSILE_YPOS + 1, INVADER_MISSILE_XPOS + 1
UnPlot INVADER_MISSILE_YPOS + 2, INVADER_MISSILE_XPOS
UnPlot INVADER_MISSILE_YPOS + 2, INVADER_MISSILE_XPOS + 1
Return
DRAW_INVADER_MISSILE:
UnPlot INVADER_MISSILE_YPOS, INVADER_MISSILE_XPOS
UnPlot INVADER_MISSILE_YPOS, INVADER_MISSILE_XPOS + 1
Plot INVADER_MISSILE_YPOS + 1, INVADER_MISSILE_XPOS
Plot INVADER_MISSILE_YPOS + 1, INVADER_MISSILE_XPOS + 1
Plot INVADER_MISSILE_YPOS + 2, INVADER_MISSILE_XPOS
Plot INVADER_MISSILE_YPOS + 2, INVADER_MISSILE_XPOS + 1
Return
'----------------------------------------------------------------------------
' Draw or clear the second Invader's missile
CLEAR_INVADER_MISSILE2:
UnPlot INVADER_MISSILE2_YPOS, INVADER_MISSILE2_XPOS
UnPlot INVADER_MISSILE2_YPOS, INVADER_MISSILE2_XPOS + 1
UnPlot INVADER_MISSILE2_YPOS + 1, INVADER_MISSILE2_XPOS
UnPlot INVADER_MISSILE2_YPOS + 1, INVADER_MISSILE2_XPOS + 1
UnPlot INVADER_MISSILE2_YPOS + 2, INVADER_MISSILE2_XPOS
UnPlot INVADER_MISSILE2_YPOS + 2, INVADER_MISSILE2_XPOS + 1
Return
DRAW_INVADER_MISSILE2:
UnPlot INVADER_MISSILE2_YPOS, INVADER_MISSILE2_XPOS
UnPlot INVADER_MISSILE2_YPOS, INVADER_MISSILE2_XPOS + 1
Plot INVADER_MISSILE2_YPOS + 1, INVADER_MISSILE2_XPOS
Plot INVADER_MISSILE2_YPOS + 1, INVADER_MISSILE2_XPOS + 1
Plot INVADER_MISSILE2_YPOS + 2, INVADER_MISSILE2_XPOS
Plot INVADER_MISSILE2_YPOS + 2, INVADER_MISSILE2_XPOS + 1
Return
'----------------------------------------------------------------------------
' Re-Draw the bases
UPDATE_BASES:
Print at 6,2,2 + BASE_HITS#0,8 + BASE_HITS#1,14 + BASE_HITS#2,_
at 6,9,2 + BASE_HITS#3,8 + BASE_HITS#4,14 + BASE_HITS#5,_
at 6,15,2 + BASE_HITS#6,8 + BASE_HITS#7,14 + BASE_HITS#8
Return
'----------------------------------------------------------------------------
' Check if BASE hit by a missile
' Each base is built from three elements (characters)
' Returns with BASE_HIT set if a hit was detected
CHECK_BASE_HIT:
BASE_HIT = FALSE ' Default to no hit detected
Select BASE_XPOS_TEST
Case 12 to 17 ' Has the missile XPOS hit BASE 1, ELEMENT 0
If BASE_HITS#0 < 5 AND BASE_ENABLED#0 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#0 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#0 = FALSE ' Disable the base element
Endif
Case 18 to 23 ' Has the missile XPOS hit BASE 1, ELEMENT 1
If BASE_HITS#1 < 5 AND BASE_ENABLED#1 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#1 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#1 = FALSE ' Disable the base element
Endif
Case 24 to 29 ' Has the missile XPOS hit BASE 1, ELEMENT 2
If BASE_HITS#2 < 5 AND BASE_ENABLED#2 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#2 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#2 = FALSE ' Disable the base element
Endif
Case 54 to 59 ' Has the missile XPOS hit BASE 2, ELEMENT 3
If BASE_HITS#3 < 5 AND BASE_ENABLED#3 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#3 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#3 = FALSE ' Disable the base element
Endif
Case 60 to 65 ' Has the missile XPOS hit BASE 2, ELEMENT 4
If BASE_HITS#4 < 5 AND BASE_ENABLED#4 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#4 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#4 = FALSE ' Disable the base element
Endif
Case 66 to 71 ' Has the missile XPOS hit BASE 2, ELEMENT 5
If BASE_HITS#5 < 5 AND BASE_ENABLED#5 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#5 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#5 = FALSE ' Disable the base element
Endif
Case 90 to 95 ' Has the missile XPOS hit BASE 3, ELEMENT 6
If BASE_HITS#6 < 5 AND BASE_ENABLED#6 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#6 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#6 = FALSE ' Disable the base element
Endif
Case 96 to 101 ' Has the missile XPOS hit BASE 3, ELEMENT 7
If BASE_HITS#7 < 5 AND BASE_ENABLED#7 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#7 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#7 = FALSE ' Disable the base element
Endif
Case 102 to 107 ' Has the missile XPOS hit BASE 3, ELEMENT 8
If BASE_HITS#8 < 5 AND BASE_ENABLED#8 = TRUE Then ' Is the base element enabled, and has had less than 5 hits ?
Inc BASE_HITS#8 ' Increment the amount of hits the base element has sustained
BASE_HIT = TRUE ' Indicate a missile has hit a target
Else
BASE_ENABLED#8 = FALSE ' Disable the base element
Endif
End Select
If BASE_HIT = TRUE Then Gosub UPDATE_BASES ' Update the base shapes if a hit was detected
Return
'----------------------------------------------------------------------------
' Move the invader's missile
' The missile can only be fired if the flag INVADER_MISSILE_FIRED is false,
' otherwise there is already a missile in the air
MOVE_INVADER_MISSILE:
If INVADER_MISSILE_FIRED = TRUE Then ' Don't enter the routine if the invader's missile is already flying
If TIME_TO_MOVE_INV_MISSILE = TRUE Then ' Is it time to move the invader's missile ?
Gosub DRAW_INVADER_MISSILE
Inc INVADER_MISSILE_YPOS
Endif
If INVADER_MISSILE_YPOS >= 63 OR INVADER_MISSILE_HIT = TRUE Then ' Has the invader's missile reached the bottom of the display or hit something ?
INVADER_MISSILE_FIRED = FALSE ' Yes. So signal the invader's missile is finished
Gosub CLEAR_INVADER_MISSILE ' Clear the invader's missile
INVADER_MISSILE_HIT = FALSE
Endif
Endif
Return
'----------------------------------------------------------------------------
' Move the invader's second missile
' The missile can only be fired if the flag INVADER_MISSILE2_FIRED is false,
' otherwise there is already a missile in the air
MOVE_INVADER_MISSILE2:
If INVADER_MISSILE2_FIRED = TRUE Then ' Don't enter the routine if the invader's missile is already flying
If TIME_TO_MOVE_INV_MISSILE2 = TRUE Then ' Is it time to move the invader's missile ?
Gosub DRAW_INVADER_MISSILE2
Inc INVADER_MISSILE2_YPOS
Endif
If INVADER_MISSILE2_YPOS >= 63 OR INVADER_MISSILE2_HIT = TRUE Then ' Has the invader's missile reached the bottom of the display or hit something ?
INVADER_MISSILE2_FIRED = FALSE ' Yes. So signal the invader's missile is finished
Gosub CLEAR_INVADER_MISSILE2 ' Clear the invader's missile
INVADER_MISSILE2_HIT = FALSE
Endif
Endif
Return
'----------------------------------------------------------------------------
' Fire an invader missile if possible
' The logic is: -
' Make sure a missile is not already in flight.
' Scan all the invaders...
' If the invader is enabled, then check if it is over the ship.
' If it is then enable a missile to be fired.
FIRE_INVADER_MISSILE:
If INVADER_MISSILE_FIRED = FALSE Then ' Is it OK to fire an invader missile ?
INVADER_LOOP = 0
Repeat ' Create a loop for all the invaders
If INVADER_ENABLED[INVADER_LOOP] = TRUE Then ' Is this invader enabled ?
Select INVADER_XPOS[INVADER_LOOP] + 5
Case SHIP_XPOS to SHIP_XPOS + 8 ' Is the invader over the ship ?
INVADER_MISSILE_FIRED = TRUE ' Signal that an invader's missile is in the air
INVADER_MISSILE_XPOS = INVADER_XPOS[INVADER_LOOP] + 5 ' Move missile XPOS to the middle of the invader
INVADER_MISSILE_YPOS = (INVADER_YPOS[INVADER_LOOP] * 8) + 8 ' Move missile YPOS to below the invader
End Select
Endif
Inc INVADER_LOOP
Until INVADER_LOOP > 17 ' Close the loop when all invaders have been scanned
Endif
Return
'----------------------------------------------------------------------------
' Fire an invader second missile if possible
' The logic is: -
' Make sure a missile is not already in flight.
' Scan all the invaders...
' If the invader is enabled, then check if it is over the ship.
' If it is then enable a missile to be fired.
Dim RANDOM_VALUE as Byte
FIRE_INVADER_MISSILE2:
If INVADER_MISSILE2_FIRED = FALSE Then ' Is it OK to fire an invader second missile ?
'If INVADER_MISSILE_XPOS < SHIP_XPOS Then
Select SHIP_XPOS
Case > INVADER_MISSILE_XPOS + RANDOM_VALUE , < INVADER_MISSILE_XPOS - RANDOM_VALUE
INVADER_LOOP = 0
Repeat ' Create a loop for all the invaders
If INVADER_ENABLED[INVADER_LOOP] = TRUE Then ' Is this invader enabled ?
Select INVADER_XPOS[INVADER_LOOP] + 5
Case SHIP_XPOS to SHIP_XPOS + 8 ' Is the invader over the ship ?
INVADER_MISSILE2_FIRED = TRUE ' Signal that an invader's missile is in the air
INVADER_MISSILE2_XPOS = INVADER_XPOS[INVADER_LOOP] + 5 ' Move missile XPOS to the middle of the invader
INVADER_MISSILE2_YPOS = (INVADER_YPOS[INVADER_LOOP] * 8) + 8 ' Move missile YPOS to below the invader
End Select
Endif
Inc INVADER_LOOP
Until INVADER_LOOP > 17 ' Close the loop when all invaders have been scanned
EndSelect
Endif
Return
'----------------------------------------------------------------------------
' Check if the invader's missile has hit something
' Returns with INVADER_MISSILE_HIT set if the invader's missile has hit something
CHECK_FOR_INVADER_MISSILE_HIT:
INVADER_MISSILE_HIT = FALSE ' Default to not hit
If INVADER_MISSILE_FIRED = TRUE Then ' First make sure that a missile is actually launched
' Check if the invader's missile has hit a BASE
If INVADER_MISSILE_YPOS >= 45 Then
BASE_XPOS_TEST = INVADER_MISSILE_XPOS ' Transfer the invader's missile XPOS for testing
Gosub CHECK_BASE_HIT ' Check if a base was hit
If BASE_HIT = TRUE Then
INVADER_MISSILE_HIT = TRUE ' Transfer the hit detector into the invader's missile detector
Return ' Return from the subroutine prematurely
Endif
Endif
' Check if the invader's missile has hit the ship
If INVADER_MISSILE_YPOS >= 56 Then
Select INVADER_MISSILE_XPOS
Case SHIP_XPOS - 1 To SHIP_XPOS + SHIP_WIDTH
Gosub DRAW_SHIP
INVADER_MISSILE_HIT = TRUE ' Indicate the invader's missile has hit something
SHIP_HIT = TRUE ' Indicate that it is the ship that has been hit
End Select
Endif
Endif
Return
'----------------------------------------------------------------------------
' Check if the invader's second missile has hit something
' Returns with INVADER_MISSILE2_HIT set if the invader's missile has hit something
CHECK_FOR_INVADER_MISSILE2_HIT:
INVADER_MISSILE2_HIT = FALSE ' Default to not hit
If INVADER_MISSILE2_FIRED = TRUE Then ' First make sure that a second missile is actually launched
' Check if the invader's second missile has hit a BASE
If INVADER_MISSILE2_YPOS >= 45 Then
BASE_XPOS_TEST = INVADER_MISSILE2_XPOS ' Transfer the invader's second missile XPOS for testing
Gosub CHECK_BASE_HIT ' Check if a base was hit
If BASE_HIT = TRUE Then
INVADER_MISSILE2_HIT = TRUE ' Transfer the hit detector into the invader's second missile detector
Return ' Return from the subroutine prematurely
Endif
Endif
' Check if the invader's missile has hit the ship
If INVADER_MISSILE2_YPOS >= 56 Then
Select INVADER_MISSILE2_XPOS
Case SHIP_XPOS - 1 To SHIP_XPOS + SHIP_WIDTH
Gosub DRAW_SHIP
INVADER_MISSILE2_HIT = TRUE ' Indicate the invader's second missile has hit something
SHIP_HIT = TRUE ' Indicate that it is the ship that has been hit
End Select
Endif
Endif
Return
'----------------------------------------------------------------------------
' Draw or clear the Ship's missile
CLEAR_MISSILE:
UnPlot MISSILE_YPOS, MISSILE_XPOS
UnPlot MISSILE_YPOS, MISSILE_XPOS + 1
UnPlot MISSILE_YPOS + 1, MISSILE_XPOS
UnPlot MISSILE_YPOS + 1, MISSILE_XPOS + 1
UnPlot MISSILE_YPOS + 2, MISSILE_XPOS
UnPlot MISSILE_YPOS + 2, MISSILE_XPOS + 1
Return
DRAW_MISSILE:
Plot MISSILE_YPOS, MISSILE_XPOS
Plot MISSILE_YPOS, MISSILE_XPOS + 1
Plot MISSILE_YPOS + 1, MISSILE_XPOS
Plot MISSILE_YPOS + 1, MISSILE_XPOS + 1
UnPlot MISSILE_YPOS + 2, MISSILE_XPOS
UnPlot MISSILE_YPOS + 2, MISSILE_XPOS + 1
Return
'----------------------------------------------------------------------------
' Draw the ship
DRAW_SHIP:
LCDWRITE 7,SHIP_XPOS,[$00,$E0,$F0,$F0,$F8,$FC,$F8,$F0,$F0,$E0,$00]
Return
'----------------------------------------------------------------------------
' Check if the ship's missile has hit something
' Returns with MISSILE_HIT set if the ship's missile has hit something
CHECK_FOR_MISSILE_HIT:
MISSILE_HIT = FALSE ' Default to not hit
SAUCER_HIT = FALSE ' Default to saucer not hit
If MISSILE_FIRED = TRUE Then ' First make sure a missile is actually launched
' Check if the ship's missile has hit a BASE
If MISSILE_YPOS = 53 Then
BASE_XPOS_TEST = MISSILE_XPOS ' Transfer the ship's missile XPOS for testing
Gosub CHECK_BASE_HIT ' Check if a base was hit
If BASE_HIT = TRUE Then
MISSILE_SOUND_ENABLE = 0 ' Disable the missile's sound
MISSILE_HIT = TRUE ' Transfer the hit detector into the missile detector
Return ' And return from the subroutine prematurely
Endif
Endif
' Check if the ship's missile has hit an invader's missile
If MISSILE_XPOS = INVADER_MISSILE_XPOS Then If MISSILE_YPOS = INVADER_MISSILE_YPOS Then
MISSILE_SOUND_ENABLE = 0 ' Disable the missile's sound
MISSILE_HIT = TRUE ' Indicate the ship's missile has hit a target
INVADER_MISSILE_HIT = TRUE ' Indicate the invader's missile has also been hit
Inc SCORE ' Increment the score by one
Return ' And return from the subroutine prematurely
Endif
' Check if the ship's missile has hit the saucer
If SAUCER_ENABLED = TRUE Then
If MISSILE_YPOS < 7 Then
Select MISSILE_XPOS
Case SAUCER_XPOS To SAUCER_XPOS + SAUCER_WIDTH
MISSILE_HIT = TRUE ' Indicate the ship's missile has hit a target
SAUCER_HIT = TRUE
SAUCER_SOUND_ENABLE = TRUE
SAUCER_FREQ = 30
LCDWRITE 0,SAUCER_XPOS,[$8C,$C5,$6B,$36,$0C,$20,$68,$CC,$96,$33,$69,$CC,$8 6,$02]
Delayms 10
LCDWRITE 0,SAUCER_XPOS,[$7F,$08,$08,$08,$7F,$00,$00,$41,$7F,$41,$00,$00,$0 1,$01,$7F,$01,$01] ' Display text HIT
SAUCER_FREQ = 20
Delayms 5
SAUCER_FREQ = 10
Delayms 10
SCORE = SCORE + (100 + SAUCER_XPOS) ' Add 100 + xpos to the score for hitting the saucer
SAUCER_SOUND_ENABLE = FALSE
Return
EndSelect
Endif
Endif
' Check if the ship's missile has hit an INVADER
INVADER_LOOP = 0
Repeat
If INVADER_ENABLED[INVADER_LOOP] = TRUE Then ' Only check if the invader is enabled
If INVADER_YPOS[INVADER_LOOP] = MISSILE_YPOS / 8 Then
Select MISSILE_XPOS
Case INVADER_XPOS[INVADER_LOOP] to INVADER_XPOS[INVADER_LOOP] + INVADER_WIDTH
INVADER_ENABLED[INVADER_LOOP] = FALSE
MISSILE_HIT = TRUE ' Indicate the ship's missile has hit a target
MISSILE_SOUND_ENABLE = 1
MISSILE_FREQ = 30
Select INVADER_LOOP ' Decide on the score depending on which invader is hit
Case 0 to 5 ' Top layer of invaders score 20
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$42,$61,$51,$49,$46,$00,$3E,$51,$49,$45,$3E,$00]
SCORE = SCORE + 20
Case 6 to 11 ' Middle layer of invaders score 10
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$42,$7F,$40,$00,$00,$3E,$51,$49,$45,$3E,$00]
SCORE = SCORE + 10
Case 12 to 17 ' Bottom layer of invaders score 5
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$3E,$51,$49,$45,$3E,$00, $27,$45,$45,$45,$39,$00]
SCORE = SCORE + 5
EndSelect
Delayms 10
MISSILE_FREQ = 20
Delayms 10
MISSILE_FREQ = 10
Delayms 20
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00] ' Erase the INVADER that was hit
Dec INVADERS_ENABLED ' Decrement the hits counter
If INVADERS_ENABLED = 1 Then ' Increase the speed substantially if only one invader left
INVADER_SPEED = 5
Else if INVADERS_ENABLED = 2 Then
INVADER_SPEED = 10 ' Increase the speed to fast if there are only two invaders left
Else
If INVADER_SPEED >= 3 Then ' Is the inveders speed greater than 3 ?
If INVADERS_ENABLED <= 4 Then ' Are there 4 or less invaders left ?
INVADER_SPEED = INVADER_SPEED - 3 ' Yes.. So increase their speed by a factor of three
Else
Dec INVADER_SPEED ' Otherwise.. Increase the speed of the remaining invaders
Endif
Endif
Endif
MISSILE_SOUND_ENABLE = 0 ' Disable the missile's sound
Return ' And return from the subroutine prematurely
Endselect
Endif
Endif
Inc INVADER_LOOP
Until INVADER_LOOP > 17
Endif
Return
'----------------------------------------------------------------------------
' Move the ship's missile
' The missile can only be fired if the flag MISSILE_FIRED is false,
' otherwise there is already a missile in the air
'
MOVE_MISSILE:
If MISSILE_FIRED = TRUE Then ' Don't enter the routine if the ship's missile is already flying
If TIME_TO_MOVE_SHIP_MISSILE = TRUE Then ' Is it time to move the ship's missile ?
Gosub DRAW_MISSILE
Dec MISSILE_YPOS
MISSILE_FREQ = 63 - MISSILE_YPOS
Endif
If MISSILE_YPOS = 0 OR MISSILE_HIT = TRUE Then ' Has the missile reached the top of the display or hit something ?
MISSILE_SOUND_ENABLE = 0
MISSILE_FIRED = FALSE ' Yes. So signal the missile is finished
Gosub CLEAR_MISSILE ' Clear the missile
MISSILE_YPOS = 63 - 9 ' Reset the missile to the bottom of the display
Endif
Endif
Return
'----------------------------------------------------------------------------
' Move the ship right
SHIP_RIGHT:
If SHIP_XPOS > 117 Then Return
Gosub DRAW_SHIP
Inc SHIP_XPOS
Return
'----------------------------------------------------------------------------
' Move the ship left
SHIP_LEFT:
If SHIP_XPOS = 0 Then Return
Gosub DRAW_SHIP
Dec SHIP_XPOS
Return
'----------------------------------------------------------------------------
' Move the INVADERS down a line
' And check whether they have reached the bottom of the screen
' Flag INVADERS_REACHED_BOTTOM will be set if they have
MOVE_INVADERS_DOWN:
INVADERS_REACHED_BOTTOM = FALSE ' Default to the invaders not at bottom of the screen
TEMP_LOOP = 18
Repeat
Dec TEMP_LOOP
If INVADER_ENABLED[TEMP_LOOP] = TRUE Then
LCDWRITE INVADER_YPOS[TEMP_LOOP],INVADER_XPOS[TEMP_LOOP],[$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00]
INVADER_YPOS[TEMP_LOOP] = INVADER_YPOS[TEMP_LOOP] + 1
If INVADER_YPOS[TEMP_LOOP] = 6 Then ' Have the invaders hit the bases ?
Str BASE_ENABLED = 0,0,0,0,0,0,0,0,0 ' Yes.. So disable them all
Str BASE_HITS = 5,5,5,5,5,5,5,5,5 ' And move their hit counters to past their thresholds
Endif
If INVADER_YPOS[TEMP_LOOP] >= 7 Then INVADERS_REACHED_BOTTOM = TRUE ' Set a flag if the invaders have reached the bottom
LCDWRITE INVADER_YPOS[TEMP_LOOP],INVADER_XPOS[TEMP_LOOP],[$00,$06,$0C,$9C,$EA,$36,$36,$EA,$9C,$0C,$06,$00]
Endif
Until TEMP_LOOP = 0
Inc INVADER_MISSILE_SPEED ' Slow down the invader's missile speed as they approach the bottom of the screen
If INVADER_SPEED >= 3 Then Dec INVADER_SPEED ' Increase the speed of the invaders
Return
'----------------------------------------------------------------------------
' Reset the invaders positions
' Each element of the arrays hold coordinates for the invaders
' Bit-0 of INVADER_ENABLED determines whether the invader is active or not (has been hit)
' Bit-1 of INVADER_ENABLED sets which graphic to use for the invader
' INVADER_XPOS holds the X position of the invader
' INVADER_YPOS holds the Y position of the invader
RESET_INVADERS:
INVADER_LOOP = 0
Repeat
INVADER_ENABLED[INVADER_LOOP] = TRUE ' Set all invaders to active and image 1
Select INVADER_LOOP
Case 0 to 5
INVADER_XPOS[INVADER_LOOP] = (INVADER_LOOP + 1) * 16
INVADER_YPOS[INVADER_LOOP] = 1
Case 6 to 11
INVADER_XPOS[INVADER_LOOP] = (INVADER_LOOP - 5) * 16
INVADER_YPOS[INVADER_LOOP] = 2
Case 12 to 17
INVADER_XPOS[INVADER_LOOP] = (INVADER_LOOP - 11) * 16
INVADER_YPOS[INVADER_LOOP] = 3
End Select
Inc INVADER_LOOP
Until INVADER_LOOP > 17
Return
'----------------------------------------------------------------------------
' Move the INVADERS
MOVE_INVADERS:
'If TIME_TO_MOVE_INVADERS = TRUE Then
TIME_TO_MOVE_INVADERS_DOWN = FALSE
If INVADERS_DIRECTION = FORWARD Then ' Are the invaders to move forward (right) ?
INVADER_LOOP = 0 ' Yes.. So reset the invader loop
Repeat ' Create a loop for all the invaders
If INVADER_ENABLED[INVADER_LOOP] = TRUE Then ' Is this invader enabled ?
INVADER_XPOS[INVADER_LOOP] = INVADER_XPOS[INVADER_LOOP] + 1 ' Yes.. So increment its XPOS
If INVADER_XPOS[INVADER_LOOP] >= INVADER_RIGHT_LIMIT Then ' Have we hit the right side of the screen ?
INVADERS_DIRECTION = BACKWARD ' Yes.. So indicate that we need to go backwards
SAUCER_ENABLED = TRUE
TIME_TO_MOVE_INVADERS_DOWN = TRUE ' and signal that we need to move the invaders down
Endif
Endif
Inc INVADER_LOOP
Until INVADER_LOOP > 17 ' Close the loop after all the invader elements have been scanned
Else ' Otherwise we go backwards (left)
INVADER_LOOP = 0 ' Reset the invader loop
Repeat ' Create a loop for all the invaders
If INVADER_ENABLED[INVADER_LOOP] = TRUE Then ' Is this invader enabled ?
INVADER_XPOS[INVADER_LOOP] = INVADER_XPOS[INVADER_LOOP] - 1 ' Yes.. So decrement its XPOS
If INVADER_XPOS[INVADER_LOOP] <= 1 Then ' Have we hit the left side of the screen ?
INVADERS_DIRECTION = FORWARD ' Yes.. So indicate that we need to go forwards
TIME_TO_MOVE_INVADERS_DOWN = TRUE ' and signal that we need to move the invaders down
Endif
Endif
Inc INVADER_LOOP
Until INVADER_LOOP > 17 ' Close the loop after all the invader elements have been scanned
Endif
If TIME_TO_MOVE_INVADERS_DOWN = TRUE Then Gosub MOVE_INVADERS_DOWN ' Do we need to move the invaders down ?
'Endif
' Fall through to DRAW_THE_INVADERS
'----------------------------------------------------------------------------
' Draw the invaders
' Draws one of two invader shapes depending on the contents of BIT variable INVADER_CHARACTER
' Each row of invaders is a different character
'INVADER TOP ROW character 1 $00,$18,$4C,$2E,$5B,$2F,$2F,$5B,$2E,$4C,$18,$00
'INVADER TOP ROW character 2 $00,$08,$2C,$5E,$0B,$1F,$1F,$0B,$5E,$2C,$08,$00
'INVADER MIDDLE ROW character 1 $00,$38,$0D,$3E,$5A,$1E,$1E,$5A,$3E,$0D,$38,$00
'INVADER MIDDLE ROW character 2 $00,$06,$48,$7F,$1A,$1E,$1E,$1A,$7F,$48,$06,$00
'INVADER BOTTOM ROW character 1 $00,$4C,$6E,$3A,$1B,$2F,$2F,$1B,$3A,$6E,$4C,$00
'INVADER BOTTOM ROW character 2 $00,$0C,$0E,$3A,$4B,$1F,$1F,$4B,$3A,$0E,$0C,$00
DRAW_INVADERS:
INVADER_LOOP = 0
Repeat
If INVADER_ENABLED[INVADER_LOOP] = TRUE Then
If INVADER_CHARACTER = 0 Then
INVADER_SOUND_ENABLE = 0
INVADER_FREQ = 90
Select INVADER_LOOP ' Decide on the score depending on which invader is hit
Case 0 to 5
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$18,$4C,$2E,$5B,$2F,$2F,$5B,$2E,$4C,$18,$00]
Case 6 to 11
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$38,$0D,$3E,$5A,$1E,$1E,$5A,$3E,$0D,$38,$00]
Case 12 to 17
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$4C,$6E,$3A,$1B,$2F,$2F,$1B,$3A,$6E,$4C,$00]
EndSelect
INVADER_SOUND_ENABLE = 1
Else
INVADER_SOUND_ENABLE = 0
INVADER_FREQ = 105
Select INVADER_LOOP ' Decide on the score depending on which invader is hit
Case 0 to 5
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$08,$2C,$5E,$0B,$1F,$1F,$0B,$5E,$2C,$08,$00]
Case 6 to 11
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$06,$48,$7F,$1A,$1E,$1E,$1A,$7F,$48,$06,$00]
Case 12 to 17
LCDWRITE INVADER_YPOS[INVADER_LOOP],INVADER_XPOS[INVADER_LOOP],[$00,$0C,$0E,$3A,$4B,$1F,$1F,$4B,$3A,$0E,$0C,$00]
EndSelect
INVADER_SOUND_ENABLE = 1
Endif
Endif
Inc INVADER_LOOP
Until INVADER_LOOP > 17
Return
'----------------------------------------------------------------------------
' Clear the saucer located at the top of the screen
CLEAR_SAUCER:
Lcdwrite 0,SAUCER_XPOS,[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
Return
'----------------------------------------------------------------------------
' Draw the saucer located at the top of the screen
DRAW_SAUCER:
Lcdwrite 0,SAUCER_XPOS,[$00,$04,$0E,$3A,$1B,$0F,$1B,$1B,$0F,$1B,$3A,$0E,$0 4,$00]
Return
'----------------------------------------------------------------------------
' Move the saucer if it is not already flying
MOVE_SAUCER:
If SAUCER_ENABLED = TRUE Then ' Don't enter the routine if the saucer is already flying
SAUCER_SOUND_ENABLE = 1 ' Enable the saucer's sound channel
If TIME_TO_MOVE_SAUCER = TRUE Then ' Is it time to move the saucer ?
Dec SAUCER_XPOS ' Move the saucer accross the screen
if SAUCER_XPOS // 2 = 0 Then
SAUCER_FREQ = 10
Else
SAUCER_FREQ = 12
Endif
Gosub DRAW_SAUCER ' Display the saucer
Endif
If SAUCER_XPOS = 0 OR SAUCER_HIT = TRUE Then ' Has the saucer reached the left of the display or been hit ?
SAUCER_ENABLED = FALSE ' Yes. So signal the sacucer is finished
Gosub CLEAR_SAUCER ' Clear the saucer
SAUCER_XPOS = 127 - SAUCER_WIDTH ' Reset the saucer to the right of the display
Print at 0,0,Dec LEVEL, " ",Dec SCORE,at 0,20,LIVES ' And display the score because it was erased by the saucer
Endif
Else
SAUCER_SOUND_ENABLE = 0 ' Disable the saucer's sound channel
Endif
Return
'----------------------------------------------------------------------------
' Determine whether a missile, ship, saucer or base should move
' governed by their individual speed controls
GOVERN_SPEEDS:
' Advance the saucers's tick (governs its speed)
Dec SAUCER_SPEED
TIME_TO_MOVE_SAUCER = FALSE
If SAUCER_SPEED = 0 Then
TIME_TO_MOVE_SAUCER = TRUE
SAUCER_SPEED = 3
Endif
' Advance the ship's tick (governs its speed)
Dec SHIP_SPEED
TIME_TO_MOVE_BASE = FALSE
If SHIP_SPEED = 0 Then
TIME_TO_MOVE_BASE = TRUE
SHIP_SPEED = 3
Endif
' Advance the invader's missile tick (governs its speed)
Inc INVADER_MISSILE_TICK
TIME_TO_MOVE_INV_MISSILE = FALSE
If INVADER_MISSILE_TICK >= INVADER_MISSILE_SPEED Then ' Set the speed for the invader's missile
TIME_TO_MOVE_INV_MISSILE = TRUE
INVADER_MISSILE_TICK = 0
Endif
' Advance the invader's second missile tick (governs its speed)
Inc INVADER_MISSILE2_TICK
TIME_TO_MOVE_INV_MISSILE2 = FALSE
If INVADER_MISSILE2_TICK >= INVADER_MISSILE2_SPEED Then ' Set the speed for the invader's second missile
TIME_TO_MOVE_INV_MISSILE2 = TRUE
INVADER_MISSILE2_TICK = 0
Endif
' Advance the ship's missile tick (governs its speed)
Dec SHIP_MISSILE_TICK
TIME_TO_MOVE_SHIP_MISSILE = FALSE
If SHIP_MISSILE_TICK = 0 Then ' Set the speed for the ship's missile
TIME_TO_MOVE_SHIP_MISSILE = TRUE
SHIP_MISSILE_TICK = 2
Endif
Return
'----------------------------------------------------------------------------
' Display the spash screen
' The subroutine re-uses some of the variables
' TEMP_LOOP, LEVEL, and INVADER_LOOP
DISPLAY_SPASH_SCREEN:
Cls
SCORE = 0
TEMP_LOOP = 0
Repeat
INVADER_LOOP = 0
Repeat
LEVEL = CREAD INVADER_SPLASH_SCREEN + SCORE
LcdWrite TEMP_LOOP,INVADER_LOOP,[LEVEL]
Inc SCORE
Inc INVADER_LOOP
Until INVADER_LOOP > 127
Inc TEMP_LOOP
Until TEMP_LOOP > 7
Return
'----------------------------------------------------------------------------
MAIN_PROGRAM_LOOP:
Gosub DISPLAY_SPASH_SCREEN
Delayms 1000
Print at 4,1,"PRESS FIRE TO START"
While FIRE_BUTTON = 1 : Wend
While FIRE_BUTTON = 0 : Wend
Delayms 50
Cls
Print at 0,7,"Scoring"
Lcdwrite 2,0,[$00,$04,$0E,$3A,$1B,$0F,$1B,$1B,$0F,$1B,$3A,$0E,$0 4,$00]
Print at 2,2," = 100+ Points"
LCDWRITE 3,0,[$00,$18,$4C,$2E,$5B,$2F,$2F,$5B,$2E,$4C,$18,$00]
Print at 3,2," = 20 Points"
LCDWRITE 4,0,[$00,$38,$0D,$3E,$5A,$1E,$1E,$5A,$3E,$0D,$38,$00]
Print at 4,2," = 10 Points"
LCDWRITE 5,0,[$00,$4C,$6E,$3A,$1B,$2F,$2F,$1B,$3A,$6E,$4C,$00]
Print at 5,2," = 5 Points"
Print at 7,1,"PRESS FIRE TO START"
While FIRE_BUTTON = 1 : Wend
While FIRE_BUTTON = 0 : Wend
Delayms 50
LEVEL = 0 ' Start at level 0
LIVES = "3" ' Set the initial lives counter to 3
SHIP_SPEED = 3
SCORE = 0
SHIP_XPOS = 64
SAUCER_SPEED = 7 ' Speed of the saucer
INVADER_SPEED = 70 ' The initial speed of the invaders
DEFAULT_INVADER_SPEED = INVADER_SPEED
TEMP_LOOP = 0
Repeat
BASE_ENABLED[TEMP_LOOP] = TRUE
BASE_HITS[TEMP_LOOP] = 0
Inc TEMP_LOOP
Until TEMP_LOOP > 8
Output PORTA ' Set all of PORTA to outputs (for sound channels)
INTERRUPT_COUNTER1 = 0
NOTE_STATUS = 0
INVADER_SOUND_COUNTER = 0
MISSILE_SOUND_COUNTER = 0
SAUCER_SOUND_COUNTER = 0
INVADER_SOUND_DURATION_COUNTER = 0
GIE = 0 ' Disable interrupts
OPTION_REG = %00000000 ' TMR0 prescaler 1:1, PORTB pullups ON
TMR0 = 0 ' Reset TMR0
INTCON = %10100000 ' Enable TMR0 Interrupt
INVADER_SOUND_ENABLE = 1 ' Enable the Invaders sound channel
INVADER_SOUND_DURATION = 20 ' Set the note duration to 20
' Main program loop starts here
' Jump to this location to implement a new sheet of invaders
NEW_SHEET:
Inc LEVEL
Cls
Gosub UPDATE_BASES ' Draw the bases (or what's left of them)
SHIP_HIT = FALSE ' Default to no hit on the ship by a missile
SAUCER_ENABLED = FALSE ' Disable the saucer
SAUCER_XPOS = 127 - SAUCER_WIDTH ' Position saucer at top tight of the screen
MISSILE_XPOS = 0
MISSILE_YPOS = 63 - 9
INVADER_MISSILE_XPOS = 0
INVADER_MISSILE_YPOS = 0
MISSILE_STATUS = 0
INVADER_MISSILE2_YPOS = 0 ' Y position of Invader's second MISSILE
INVADER_MISSILE2_XPOS = 0 ' X position of Invader's second MISSILE
TIME_TO_MOVE_INV_MISSILE2 = FALSE ' Indicate time to move the invader's second missile
INVADER_MISSILE2_FIRED = FALSE ' TRUE if Invader's second MISSILE in the air
INVADER_MISSILE2_HIT = FALSE ' Default to not hit anything
TIME_TO_MOVE_BASE = FALSE
Gosub CLEAR_INVADER_MISSILE
Gosub CLEAR_MISSILE
Gosub DRAW_SHIP ' Draw the initial ship
Dec DEFAULT_INVADER_SPEED ' Speed up the invaders every new sheet
INVADER_SPEED = DEFAULT_INVADER_SPEED ' Transfer the speed into the actual speed altering variable
Clear INVADER_TICK
Clear INVADER_MISSILE_TICK
Clear INVADER_MISSILE2_TICK
SHIP_MISSILE_TICK = 2
INVADERS_REACHED_BOTTOM = FALSE ' Default to the invaders not at the bottom of the screen
INVADER_CHARACTER = 0
INVADER_MISSILE_SPEED = 5 ' Default speed of the invader's missile
INVADER_MISSILE2_SPEED = 4
INVADERS_DIRECTION = FORWARD ' Default to the invaders moving right
INVADERS_ENABLED = 18 ' All 18 invaders are enabled
Gosub RESET_INVADERS ' Reset all the invaders positions
Gosub DRAW_INVADERS ' Place all the invaders on the screen
Print at 0,0,Dec LEVEL, " ",Dec SCORE,at 0,20,LIVES
While 1 = 1
RANDOM_VALUE = RANDOM
RANDOM_VALUE = RANDOM_VALUE & %00111000
Inc INVADER_TICK
TIME_TO_MOVE_INVADERS = FALSE
If INVADER_TICK > INVADER_SPEED Then
INVADER_TICK = 0
'TIME_TO_MOVE_INVADERS = TRUE
'If TIME_TO_MOVE_INVADERS = TRUE Then
Gosub MOVE_INVADERS
Gosub MOVE_INVADERS
INVADER_CHARACTER = ~INVADER_CHARACTER ' Use a new invader character
If INVADERS_REACHED_BOTTOM = TRUE Then GAME_OVER
Endif
Gosub MOVE_SAUCER ' Move the flying saucer (if required)
Gosub GOVERN_SPEEDS ' Check whether a piece should be moving
If L_BUTTON = 0 Then Gosub SHIP_LEFT ' Move ship left if LEFT button pressed
If R_BUTTON = 0 Then Gosub SHIP_RIGHT ' Move ship right if RIGHT button pressed
If FIRE_BUTTON = 0 Then If MISSILE_FIRED = FALSE Then ' Has the FIRE button been pressed and the ship's missile not already flying ?
SEED INVADER_SOUND_COUNTER
MISSILE_FIRED = TRUE ' Yes.. So signal we need the ship's missile FIRED
MISSILE_XPOS = SHIP_XPOS + 4 ' Place the ship's missile's xpos at the middle of the ship's shape
MISSILE_SOUND_ENABLE = 1 ' Enable the missile's sound
Endif
Gosub MOVE_MISSILE ' Move the ship's missile if OK to do so
Gosub CHECK_FOR_MISSILE_HIT ' Check if the ship's missile has hit anything
If MISSILE_HIT = TRUE OR SAUCER_HIT = TRUE Then
If BASE_HIT = FALSE Then
'Print at 0,19,Dec2 INVADERS_ENABLED," " ' Display the INVADER hits count
Print at 0,0,Dec LEVEL, " ",Dec SCORE,at 0,20,LIVES
Endif
Endif
If INVADER_CHARACTER = 1 Then
Gosub FIRE_INVADER_MISSILE ' Fire an invader missile is possible
Endif
Gosub MOVE_INVADER_MISSILE ' Move the invader's missile (if fired)
Gosub CHECK_FOR_INVADER_MISSILE_HIT ' Check if the invader's missile has hit anything
If INVADERS_ENABLED = 0 Then ' Have all the invaders been destroyed ?
INVADERS_ENABLED = 18 ' Yes.. So enable them all again
If INVADER_SPEED >= 3 Then Dec INVADER_SPEED ' Increase the speed of the invaders
Goto NEW_SHEET ' and start a new sheet
Endif
If LEVEL > 10 Then ' Add a second invader missile after level 10
If INVADER_CHARACTER = 0 then
Gosub FIRE_INVADER_MISSILE2 ' Fire an invader missile is possible
Endif
Gosub MOVE_INVADER_MISSILE2 ' Move the invader's missile (if fired)
Gosub CHECK_FOR_INVADER_MISSILE2_HIT ' Check if the invader's missile has hit anything
Endif
If SHIP_HIT = TRUE Then ' Has the ship been hit ?
SHIP_HIT = FALSE
SAUCER_SOUND_ENABLE = 1 ' Yes. So enable SAUCER sound channel
MISSILE_SOUND_ENABLE = 1 ' Enable MISSILE sound channel
MISSILE_FREQ = 70 ' Set MISSILE channel frequency to 70
SAUCER_FREQ = 90 ' Set SAUCER channel frequency to 90
LCDWRITE 7,SHIP_XPOS,[$10,$24,$AC,$F8,$F0,$E0,$F0,$F8,$AC,$24,$10] ' Draw first part of ship exploding
Delayms 40 ' Leave the graphic on the screen for 40ms
SAUCER_FREQ = 100 ' Increase the SAUCER channel's frequency
MISSILE_FREQ = 120 ' Increase the MISSILE channel's frequency
LCDWRITE 7,SHIP_XPOS,[$00,$20,$28,$F0,$A8,$C0,$E0,$F0,$28,$04,$00] ' Draw second part of ship exploding
Delayms 40 ' Leave the graphic on the screen for 40ms
SAUCER_FREQ = 150 ' Increase the SAUCER channel's frequency
MISSILE_FREQ = 135 ' Increase the MISSILE channel's frequency
LCDWRITE 7,SHIP_XPOS,[$00,$00,$30,$60,$80,$C0,$60,$30,$00,$00,$00] ' Draw third part of ship exploding
Delayms 100
LCDWRITE 7,SHIP_XPOS,[$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00] ' Clear the ship graphic
Delayms 100 ' Leave the graphic on the screen for 100ms
LIVES = LIVES - 1 ' Decrement the lives counter
MISSILE_SOUND_ENABLE = 0 ' Disable the MISSILE sound channel
SAUCER_SOUND_ENABLE = 0 ' Disable the SAUCER sound channel
If LIVES > "0" Then ' Do we have any lives left ?
LCDWRITE 7,SHIP_XPOS,[$00,$E0,$F0,$F0,$F8,$FC,$F8,$F0,$F0,$E0,$00] ' Yes. So Re-draw the ship and carry on
Print at 0,20,LIVES ' Update the Display for the amount of lives
Else ' Otherwise, we don't have any lives left
Goto GAME_OVER ' So game over
Endif
Endif
Delayms 6 ' Main game speed setting
Wend
'--------------------------------------------------------------------
' Explode the ship when the game is over
GAME_OVER:
Print at 0,0,Dec LEVEL, " ",Dec SCORE,at 0,20,LIVES
SAUCER_SOUND_ENABLE = TRUE ' Enable SAUCER sound channel
MISSILE_SOUND_ENABLE = TRUE ' Enable MISSILE sound channel
MISSILE_FREQ = 70 ' Set MISSILE channel frequency to 70
SAUCER_FREQ = 90 ' Set SAUCER channel frequency to 90
TEMP_LOOP = 1
Repeat
MISSILE_FREQ = MISSILE_FREQ - TEMP_LOOP
SAUCER_FREQ = SAUCER_FREQ - TEMP_LOOP
Delayms 10 + TEMP_LOOP
Circle 1,SHIP_XPOS + 5,63,TEMP_LOOP
If TEMP_LOOP > 10 Then
Circle 0,SHIP_XPOS + 5,63,TEMP_LOOP - 10
Endif
TEMP_LOOP = TEMP_LOOP + 2
Until TEMP_LOOP > 24
SAUCER_SOUND_ENABLE = FALSE ' Disable SAUCER sound channel
MISSILE_SOUND_ENABLE = FALSE ' Disable MISSILE sound channel
TEMP_LOOP = 1
Repeat
Circle 0,SHIP_XPOS + 5,63,TEMP_LOOP
TEMP_LOOP = TEMP_LOOP + 2
Until TEMP_LOOP > 24
'Cls
Print at 3,6,INVERSE 1,"GAME OVER", INVERSE 0
Delayms 500
Print at 4,1,"PRESS FIRE TO START"
While FIRE_BUTTON = 1 : Wend
Delayms 50
While FIRE_BUTTON = 0 : Wend
Delayms 50
Goto MAIN_PROGRAM_LOOP
'--------------------------------------------------------------------
' Font CDATA table for space invaders game
FONT:- CData $00,$00,$00,$00,$00,$00 'Graphic Character 0
CData $FF,$FF,$FF,$FF,$FF,$FF 'Graphic Character 1
CData $E0,$F0,$F8,$FC,$FC,$FE ' Left side of base complete (Character 2)
CData $C0,$B0,$B0,$70,$EC,$F8 ' Left side of base after hit 1 (Character 3)
CData $C0,$A0,$B0,$70,$AC,$28 ' Left side of base after hit 2 (Character 4)
CData $40,$A0,$B0,$70,$A0,$20 ' Left side of base after hit 3 (Character 5)
CData $40,$80,$80,$40,$A0,$20 ' Left side of base after hit 4 (Character 6)
CData $00,$00,$00,$00,$00,$00 ' Left side of base after hit 5 (Character 7)
CData $FE,$FE,$FE,$FE,$FE,$FE ' Middle of base complete (Character 8)
CData $FE,$DE,$EC,$F0,$F8,$FE ' Middle of base after hit 1 (Character 9)
CData $F8,$DE,$E4,$F0,$D8,$9E ' Middle of base after hit 2 (Character 10)
CData $B8,$DE,$A4,$B0,$48,$B4 ' Middle of base after hit 3 (Character 11)
CData $34,$58,$A4,$B8,$48,$34 ' Middle of base after hit 4 (Character 12)
CData $00,$00,$00,$00,$00,$00 ' Middle of base after hit 5 (Character 13)
CData $FE,$FC,$FC,$F8,$F0,$E0 ' Right side of base complete (Character 14)
CData $C0,$B0,$B0,$70,$EC,$F8 ' Right side of base after hit 1 (Character 15)
CData $C0,$A0,$B0,$70,$AC,$28 ' Right side of base after hit 2 (Character 16)
CData $40,$A0,$B0,$70,$A0,$20 ' Right side of base after hit 3 (Character 17)
CData $40,$80,$80,$40,$A0,$20 ' Right side of base after hit 4 (Character 18)
CData $00,$00,$00,$00,$00,$00 ' Right side of base after hit 5 (Character 19)
CData $FF,$00,$00,$00,$00,$00 'Graphic character 20
CData $00,$00,$00,$00,$00,$FF 'Graphic character 21
CData $FF,$01,$01,$01,$01,$01 'Graphic character 22
CData $01,$01,$01,$01,$01,$FF 'Graphic character 23
CData $FF,$80,$80,$80,$80,$80 'Graphic character 24
CData $80,$80,$80,$80,$80,$FF 'Graphic character 25
CData $00,$00,$00,$00,$F0,$F0 'User defined character 26
CData $00,$00,$00,$00,$0F,$0F 'User defined character 27
CData $00,$00,$00,$00,$00,$00 'User defined character 28
CData $00,$00,$00,$00,$00,$00 'User defined character 29
CData $00,$00,$00,$00,$00,$00 'User defined character 30
CData $00,$00,$00,$00,$00,$00 'User defined character 31
CData $00,$00,$00,$00,$00,$00 '32 - - 20
CData $00,$00,$4F,$00,$00,$00 '33 - ! - 21
CData $00,$07,$00,$07,$00,$00 '34 - " - 22
CData $14,$7F,$14,$7F,$14,$00 '35 - # - 23
CData $24,$2A,$7F,$2A,$12,$00 '36 - $ - 24
CData $23,$13,$08,$64,$62,$00 '37 - % - 25
CData $36,$49,$55,$22,$50,$00 '38 - & - 26
CData $00,$05,$03,$00,$00,$00 '39 - ' - 27
CData $1C,$22,$41,$00,$00,$00 '40 - ( - 28
CData $00,$00,$41,$22,$1C,$00 '41 - ) - 29
CData $14,$08,$3E,$08,$14,$00 '42 - * - 2A
CData $08,$08,$3E,$08,$08,$00 '43 - + - 2B
CData $00,$50,$30,$00,$00,$00 '44 - , - 2C
CData $08,$08,$08,$08,$08,$00 '45 - - - 2D
CData $00,$60,$60,$00,$00,$00 '46 - . - 2E
CData $20,$10,$08,$04,$02,$00 '47 - / - 2F
CData $3E,$51,$49,$45,$3E,$00 '48 - 0 - 30
CData $00,$42,$7F,$40,$00,$00 '49 - 1 - 31
CData $42,$61,$51,$49,$46,$00 '50 - 2 - 32
CData $21,$41,$45,$4B,$31,$00 '51 - 3 - 33
CData $18,$14,$12,$7F,$10,$00 '52 - 4 - 34
CData $27,$45,$45,$45,$39,$00 '53 - 5 - 35
CData $3C,$4A,$49,$49,$30,$00 '54 - 6 - 36
CData $01,$71,$09,$05,$03,$00 '55 - 7 - 37
CData $36,$49,$49,$49,$36,$00 '56 - 8 - 38
CData $06,$49,$49,$49,$3E,$00 '57 - 9 - 39
CData $00,$36,$36,$00,$00,$00 '58 - : - 3A
CData $00,$56,$36,$00,$00,$00 '59 - ; - 3B
CData $08,$14,$22,$41,$00,$00 '60 - < - 3C
CData $14,$14,$14,$14,$14,$00 '61 - = - 3D
CData $00,$41,$22,$14,$08,$00 '62 - > - 3E
CData $02,$01,$51,$09,$06,$00 '63 - ? - 3F
CData $32,$49,$79,$41,$3E,$00 '64 - @ - 40
CData $7E,$11,$11,$11,$7E,$00 '65 - A - 41
CData $7F,$49,$49,$49,$36,$00 '66 - B - 42
CData $3E,$41,$41,$41,$22,$00 '67 - C - 43
CData $7F,$41,$41,$22,$1C,$00 '68 - D - 44
CData $7F,$49,$49,$49,$41,$00 '69 - E - 45
CData $7F,$09,$09,$09,$01,$00 '70 - F - 46
CData $3E,$41,$49,$49,$7A,$00 '71 - G - 47
CData $7F,$08,$08,$08,$7F,$00 '72 - H - 48
CData $00,$41,$7F,$41,$00,$00 '73 - I - 49
CData $20,$40,$41,$3F,$01,$00 '74 - J - 4A
CData $7F,$08,$14,$22,$41,$00 '75 - K - 4B
CData $7F,$40,$40,$40,$40,$00 '76 - L - 4C
CData $7F,$02,$0C,$02,$7F,$00 '77 - M - 4D
CData $7F,$04,$08,$10,$7F,$00 '78 - N - 4E
CData $3E,$41,$41,$41,$3E,$00 '79 - O - 4F
CData $7F,$09,$09,$09,$06,$00 '80 - P - 50
CData $3E,$41,$51,$21,$5E,$00 '81 - Q - 51
CData $7F,$09,$19,$29,$46,$00 '82 - R - 52
CData $46,$49,$49,$49,$31,$00 '83 - S - 53
CData $01,$01,$7F,$01,$01,$00 '84 - T - 54
CData $3F,$40,$40,$40,$3F,$00 '85 - U - 55
CData $1F,$20,$40,$20,$1F,$00 '86 - V - 56
CData $3F,$40,$38,$40,$3F,$00 '87 - W - 57
CData $63,$14,$08,$14,$63,$00 '88 - X - 58
CData $07,$08,$70,$08,$07,$00 '89 - Y - 59
CData $61,$51,$49,$45,$43,$00 '90 - Z - 5A
CData $7F,$41,$41,$00,$00,$00 '91 - [ - 5B
CData $02,$04,$08,$10,$20,$00 '92 - \ - 5C
CData $00,$00,$41,$41,$7F,$00 '93 - ] - 5D
CData $04,$02,$01,$02,$04,$00 '94 - ^ - 5E
CData $40,$40,$40,$40,$40,$00 '95 - _ - 5F
CData $00,$01,$02,$04,$00,$00 '96 - ` - 60
CData $20,$54,$54,$54,$78,$00 '97 - a - 61
CData $7F,$48,$44,$44,$38,$00 '98 - b - 62
CData $38,$44,$44,$44,$20,$00 '99 - c - 63
CData $38,$44,$44,$48,$7F,$00 '100 d - 64
CData $38,$54,$54,$54,$18,$00 '101 e - 65
CData $08,$7E,$09,$01,$02,$00 '102 f - 66
CData $0C,$52,$52,$52,$3E,$00 '103 g - 67
CData $7F,$08,$04,$04,$78,$00 '104 h - 68
CData $00,$44,$7D,$40,$00,$00 '105 i - 69
CData $00,$20,$40,$44,$3D,$00 '106 j - 6A
CData $7F,$10,$28,$44,$00,$00 '107 k - 6B
CData $00,$41,$7F,$40,$00,$00 '108 l - 6C
CData $7C,$04,$18,$04,$78,$00 '109 m - 6D
CData $7C,$08,$04,$04,$78,$00 '110 n - 6E
CData $38,$44,$44,$44,$38,$00 '111 o - 6F
CData $7C,$14,$14,$14,$08,$00 '112 p - 70
CData $08,$14,$14,$18,$7C,$00 '113 q - 71
CData $7C,$08,$04,$04,$08,$00 '114 r - 72
CData $48,$54,$54,$54,$20,$00 '115 s - 73
CData $04,$3F,$44,$40,$20,$00 '116 t - 74
CData $3C,$40,$40,$20,$7C,$00 '117 u - 75
CData $1C,$20,$40,$20,$1C,$00 '118 v - 76
CData $3C,$40,$30,$40,$3C,$00 '119 w - 77
CData $44,$28,$10,$28,$44,$00 '120 x - 78
CData $0C,$50,$50,$50,$3C,$00 '121 y - 79
CData $44,$64,$54,$4C,$44,$00 '122 z - 7A
CData $08,$36,$41,$00,$00,$00 '123 { - 7B
CData $00,$00,$7F,$00,$00,$00 '124 | - 7C
CData $00,$00,$41,$36,$08,$00 '125 } - 7D
CData $00,$08,$04,$08,$04,$00 '126 ~ - 7E
'--------------------------------------------------------------------
INVADER_SPLASH_SCREEN:
CDATA $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$40,$70,$78,_
$7C,$7C,$7C,$7C,$7C,$FC,$F8,$F0,$E0,$C0,$C0,$7C,$7 C,$7C,$7C,$7C,_
$7C,$7C,$7C,$7C,$7C,$7C,$F8,$F0,$E0,$C0,$00,$00,$8 0,$7C,$7C,$7C,_
$7C,$7C,$7C,$7C,$7C,$70,$80,$00,$00,$00,$80,$C0,$F 0,$F8,$3E,$3E,_
$3E,$3E,$3E,$3E,$3E,$3E,$3E,$7C,$F8,$E0,$C0,$FE,$F E,$3E,$3E,$3E,_
$3E,$3E,$3E,$3E,$3E,$3E,$3E,$3E,$20,$A0,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$60,$F0,$0C,$06,$0 6,$06,$06,$86,_
$86,$86,$06,$06,$06,$0C,$19,$F3,$C7,$3F,$FF,$02,$0 2,$02,$02,$02,_
$82,$82,$82,$82,$02,$06,$0C,$19,$33,$E7,$F8,$00,$F F,$02,$02,$02,_
$02,$02,$02,$02,$02,$06,$FF,$00,$00,$FE,$FF,$F3,$7 1,$08,$0C,$06,_
$02,$02,$82,$82,$82,$02,$02,$02,$07,$0F,$FF,$3F,$C 0,$FC,$1E,$02,_
$02,$02,$03,$C3,$C3,$C3,$C3,$C3,$C3,$43,$73,$1F,$0 3,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$03,$3C,$E0,$8 0,$00,$00,$03,_
$1E,$61,$5E,$58,$58,$58,$58,$99,$BF,$40,$03,$FF,$C 0,$00,$00,$00,_
$01,$FF,$83,$FF,$00,$00,$00,$00,$00,$FF,$07,$FE,$0 F,$00,$00,$00,_
$F8,$7F,$E0,$00,$00,$00,$0F,$FC,$00,$FF,$01,$FF,$0 0,$00,$00,$00,_
$00,$FE,$1F,$0C,$0F,$08,$08,$08,$F8,$7E,$07,$FC,$1 F,$03,$00,$00,_
$00,$00,$0F,$0F,$0D,$E8,$38,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 1,$63,$E6,$2C,_
$28,$28,$68,$E8,$98,$F0,$00,$01,$01,$07,$FE,$83,$7 F,$F0,$00,$00,_
$00,$01,$E1,$21,$60,$30,$30,$0C,$06,$01,$00,$FF,$0 0,$00,$00,$00,_
$8F,$8C,$8F,$00,$00,$00,$00,$3F,$F8,$3F,$FE,$07,$0 0,$00,$00,$80,_
$FF,$C1,$FE,$0E,$02,$02,$82,$FB,$1F,$E0,$FF,$03,$0 0,$00,$00,$F0,_
$BE,$83,$83,$E3,$82,$83,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0 0,$00,$00,$00,_
$00,$00,$00,$00,$00,$C0,$40,$40,$5C,$7C,$7C,$FC,$F C,$F0,$40,$4C,_
$7C,$7C,$7C,$FC,$FC,$F8,$20,$00,$0C,$3C,$3C,$7C,$F C,$FC,$F3,$06,_
$0C,$18,$30,$71,$F1,$F1,$F1,$D0,$18,$0C,$3F,$3D,$3 C,$FF,$FC,$F8,_
$18,$18,$DF,$1E,$3C,$3C,$3C,$3C,$3C,$3C,$3F,$F8,$0 8,$08,$08,$0E,_
$0F,$3C,$3F,$3F,$38,$38,$38,$38,$3F,$3E,$7D,$F3,$E C,$08,$F8,$F8,_
$78,$38,$38,$38,$3C,$3F,$3F,$3E,$3E,$3F,$38,$38,$3 8,$E8,$88,$F8,_
$78,$38,$38,$3C,$3F,$3E,$3E,$38,$30,$20,$40,$80,$C 0,$F0,$F8,$FC,_
$FE,$7E,$3E,$1E,$1E,$1E,$1E,$1E,$1C,$10,$00,$40,$8 0,$00,$00,$00,_
$00,$06,$0E,$36,$C6,$82,$02,$06,$1C,$30,$C6,$8F,$3 B,$E3,$82,$02,_
$06,$0C,$30,$6E,$FB,$C3,$03,$02,$02,$02,$1E,$73,$9 F,$73,$C3,$83,_
$03,$07,$1C,$70,$C1,$07,$7F,$C3,$03,$03,$03,$03,$7 F,$C0,$FF,$FF,_
$FF,$FF,$03,$03,$03,$03,$03,$03,$03,$07,$3E,$C3,$7 F,$E0,$00,$00,_
$FF,$03,$03,$01,$E1,$E1,$21,$E1,$01,$01,$03,$06,$8 F,$F8,$FF,$3F,_
$FC,$07,$01,$01,$01,$01,$E1,$E1,$A1,$A1,$A1,$21,$E 1,$F1,$3F,$E3,_
$3C,$07,$01,$01,$01,$C1,$61,$E1,$61,$01,$01,$01,$0 1,$C7,$7F,$99,_
$70,$3C,$06,$02,$03,$C1,$31,$B1,$71,$31,$01,$01,$8 1,$C1,$76,$18,_
$00,$00,$00,$00,$00,$01,$06,$0C,$30,$40,$80,$01,$0 6,$0C,$31,$C6,_
$9C,$70,$C0,$00,$00,$01,$07,$00,$80,$00,$00,$00,$0 7,$1E,$F0,$83,_
$0E,$38,$E0,$80,$00,$07,$0C,$7F,$80,$00,$00,$00,$0 0,$FF,$07,$FF,_
$FF,$FF,$00,$00,$00,$00,$FF,$E0,$00,$00,$00,$07,$F 8,$8F,$FC,$80,_
$FF,$00,$00,$00,$FF,$07,$00,$FF,$00,$00,$00,$80,$F F,$FF,$8F,$7E,_
$03,$00,$00,$00,$00,$E4,$A7,$A6,$A6,$26,$FE,$7E,$C F,$F9,$0F,$01,_
$00,$00,$C0,$C8,$CE,$09,$07,$01,$30,$F0,$68,$2C,$2 7,$39,$3E,$C3,_
$40,$40,$C8,$4E,$0B,$08,$0A,$9B,$F2,$03,$03,$03,$0 1,$00,$00,$00,_
$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$02,$0 C,$30,$60,$C0,_
$C1,$C6,$5D,$F7,$CC,$30,$E0,$C0,$C0,$47,$5E,$6C,$3 0,$60,$40,$43,_
$5E,$74,$04,$05,$06,$18,$70,$40,$40,$40,$40,$40,$4 0,$47,$7E,$07,_
$01,$7F,$40,$40,$40,$40,$79,$09,$09,$70,$40,$40,$4 0,$4F,$74,$01,_
$7F,$40,$40,$40,$47,$44,$46,$41,$40,$20,$10,$0F,$0 1,$43,$7F,$40,_
$40,$40,$40,$40,$4F,$48,$48,$48,$78,$08,$70,$5E,$4 3,$40,$40,$60,_
$38,$47,$7B,$47,$41,$40,$70,$1C,$07,$03,$3E,$61,$4 1,$61,$69,$6F,_
$6D,$66,$61,$30,$10,$1C,$06,$03,$00,$00,$00,$00,$0 0,$00,$00,$00


Menu
Recent Articles


Using PDS with SPI GLCD based on ST7565R Controller
Graphic LCDs based on the ST7565 are cheaper then GLCDs with other controllers. SPI requires only four pins. If the circuit