top of page
Search
cedarcantab

Space Invaders in Phaser 3 (Part 14): Typewriting Text and the End of Game



Game Over Sequence

When the player is hit, and last life is lost it is game over. As soon as the player is hit, the aliens stop moving, and the player explosion starts. As soon as the explosion animation is complete, the GAME OVER text is printed in the upper part of the screen in typewriter style.


Then there is a delay before the screen is cleared, and goes back to the INSERT COIN screen.


The key part of the relevant code is as follows.


16C9: 21 18 2D        LD      HL,$2D18            ; Screen coordinates
16CC: 11 A6 1A        LD      DE,$1AA6            ; "GAME OVER PLAYER< >"
16CF: 0E 0A           LD      C,$0A               ; Just the "GAME OVER" part
16D1: CD 93 0A        CALL    PrintMessageDel     ; Print message
16D4: CD B6 0A        CALL    TwoSecDelay         ; Long delay
16D7: CD D6 09        CALL    ClearPlayField      ; Clear center window

First the screen coordinate for printing the GAME OVER text is loaded into register HL. $2D18 is (72,56) in terms of the top left hand corner of the text. Then the location where the actual text message is held is loaded into register DE, and the number of characters to be printed loaded into register C.


Then PrintMessageDel is called to print the GAME OVER text in type writer style. The relevant code is below. It is simpe enough. All it does is draw each character and between each character, a counter is decremented frm 7 to 1 to loop through 6 refresh cycles before the next character is drawn; ie 100 milli-seconds delay is created between each character.


PrintMessageDel:
; Print message from DE to screen at HL (length in C) with a
; delay between letters.
0A93: D5              PUSH    DE                  ; Preserve
0A94: 1A              LD      A,(DE)              ; Get character
0A95: CD FF 08        CALL    DrawChar            ; Draw character on screen
0A98: D1              POP     DE                  ; Preserve
0A99: 3E 07           LD      A,$07               ; Delay between letters
0A9B: 32 C0 20        LD      (isrDelay),A        ; Set counter
0A9E: 3A C0 20        LD      A,(isrDelay)        ; Get counter
0AA1: 3D              DEC     A                   ; Is it 1?
0AA2: C2 9E 0A        JP      NZ,$0A9E            ; No ... wait on it
0AA5: 13              INC     DE                  ; Next in message
0AA6: 0D              DEC     C                   ; All done?
0AA7: C2 93 0A        JP      NZ,PrintMessageDel  ; No ... do all
0AAA: C9              RET                         ; Out

Javascript / Phaser 3 version

Despite all the amazing functionalities available in Phaser 3, there is no built-in function to print a string in type writer style, at least as far as I am aware. So how to recreate this simple effect?


Of course one could copy the logic in the above, creating a counting to be updated within the update function. That would be straightforward enough. However, having experimented with various different ways of achieving the same effect, I have ended up creating the following, which uses Phaser's timer event.


class TypeWrittenText {
  // typewrites a single line of text passed as an object with x,y
  constructor(scene, textObj, delay = 0) {
    this.scene = scene;
    this.textObj = textObj;
    this.textLength = textObj.text.length;
    this.lineCount = 0;
    this.letterCount = 1;
    this.displayedText = this.scene.add.bitmapText(this.textObj.x, this.textObj.y, 'TAITO')
    this.delay = delay;
  }
  
  typeWrite(delay = 0) {
    this.delay = delay;
    this.scene.time.delayedCall(this.delay, this.startWriting, [], this)
  }
  
  startWriting() {
    this.typer = this.scene.time.addEvent({
      callback: () => {
        this.displayedText.setText( this.textObj.text.substring(0,this.letterCount));
        this.letterCount ++;
      },
      repeat: this.textLength -1,
      delay: 100
    });
  }
  
  setText(text) {
    this.displayedText.setText(text)
  }
  
  isTyping() {
    return (this.typer.repeatCount > 0);
  }
}

To use the above, one creates a text object to be type written, like so. This simply creates an object and does not actually display anything on screen.


this.gameOverLabel = new TypeWrittenText(this, {x: 72,y:56, text: "GAME OVER"});

To display the text on the screen, you call the typeWrite method. I have built it so that it takes one parameter which you can use to delay the start of the type-writing sequence, in milli-seconds. This makes coding the ending sequence a bit easier, like so. The below code will start the GAME OVER type writing sequence, after 1000 milli-seconds (set by MainGame.gameOverLabelOnScreen


case MainGame.Status.GAMEOVER:
        this.gameOverLabel.typeWrite(MainGame.respawnLabelOnScreen);
        this.time.delayedCall(MainGame.gameOverDelay, this.restartGame, [], this)
        break;

The CodePen is available below.







3 views0 comments

Comments


記事: Blog2_Post
bottom of page