UC3D
UC3D

Reputation: 383

How to properly import variables and functions in angular typescript files?

So i'm making a html canvas game in angular that will have lots of script files and I want to make it with optimal readability and performance.

Here is my code so far:

import { Component, OnInit } from '@angular/core';
import { Player } from './scripts/entities';
declare let $: any;

@Component({
  selector: 'app-game-screen',
  templateUrl: './game-screen.component.html',
  styleUrls: ['./game-screen.component.scss']
})
export class GameScreenComponent implements OnInit {

  constructor() { }

  ngOnInit() {
    //Draw canvas
    let sw = $("#container").width(); // Screen width
    let sh = $("#container").height(); // Screen height

    //Player canvas
    let canvas: any = document.querySelector("#gameScreen");
    canvas.width = sw;
    canvas.height = sh;
    let ctx = canvas.getContext("2d");

    //Test canvas
    let testCanvas: any = document.querySelector("#testScreen");
    testCanvas.width = sw;
    testCanvas.height = sh;
    let test = testCanvas.getContext("2d");

    //function to clear canvas
    function clearCanvas(screen) {
      screen.clearRect(0, 0, canvas.width, canvas.height);
    }
    //!Draw canvas

    // Entities - player, enemies, bosses
    const player = new Player('Player', sw / 2, sh / 2, sw / 10, sh / 7, ctx);
    player.draw();

    const posMarker = new Player('Position indicator', sw / 2, sh / 2, 5, 5, test);
    posMarker.boxColor = 'red';
    posMarker.draw();

    // ! Entities - player, enemies, bosses

    //Controls
    document.addEventListener('keydown', keyDownHandler, false);
    document.addEventListener('keyup', keyUpHandler, false);

    let rightPressed = false;
    let leftPressed = false;
    let upPressed = false;
    let downPressed = false;

    function keyDownHandler(event) {
      if (event.keyCode == 39) {
        rightPressed = true;
      }
      else if (event.keyCode == 37) {
        leftPressed = true;
      }
      if (event.keyCode == 40) {
        downPressed = true;
      }
      else if (event.keyCode == 38) {
        upPressed = true;
      }
    }

    function keyUpHandler(event) {
      if (event.keyCode == 39) {
        rightPressed = false;
      }
      else if (event.keyCode == 37) {
        leftPressed = false;
      }
      if (event.keyCode == 40) {
        downPressed = false;
      }
      else if (event.keyCode == 38) {
        upPressed = false;
      }
    }

    function controlMove() {
      clearCanvas(ctx);
      if (rightPressed) {
        player.x += 10;
      }
      else if (leftPressed) {
        player.x -= player.speed;
      }
      if (downPressed) {
        player.y += player.speed;
      }
      else if (upPressed) {
        player.y -= player.speed;
      }
      //Border limitations
      if (player.x - player.w / 2 < 0) { player.x = player.w / 2 }
      if (player.x + player.w / 2 > sw) { player.x = sw - player.w / 2 }
      if (player.y - player.h / 2 < 0) { player.y = player.h / 2 }
      if (player.y + player.h / 2 > sh) { player.y = sh - player.h / 2 }
      //!Border limitations
      player.draw();
      requestAnimationFrame(controlMove);
    }
    controlMove();
    // ! Controls

  }

}

Let's say i want this whole part about controls in another external file. How would I go on about doing that?

    //Controls
    document.addEventListener('keydown', keyDownHandler, false);
    document.addEventListener('keyup', keyUpHandler, false);

    let rightPressed = false;
    let leftPressed = false;
    let upPressed = false;
    let downPressed = false;

    function keyDownHandler(event) {
      if (event.keyCode == 39) {
        rightPressed = true;
      }
      else if (event.keyCode == 37) {
        leftPressed = true;
      }
      if (event.keyCode == 40) {
        downPressed = true;
      }
      else if (event.keyCode == 38) {
        upPressed = true;
      }
    }

    function keyUpHandler(event) {
      if (event.keyCode == 39) {
        rightPressed = false;
      }
      else if (event.keyCode == 37) {
        leftPressed = false;
      }
      if (event.keyCode == 40) {
        downPressed = false;
      }
      else if (event.keyCode == 38) {
        upPressed = false;
      }
    }

    function controlMove() {
      clearCanvas(ctx);
      if (rightPressed) {
        player.x += 10;
      }
      else if (leftPressed) {
        player.x -= player.speed;
      }
      if (downPressed) {
        player.y += player.speed;
      }
      else if (upPressed) {
        player.y -= player.speed;
      }
      //Border limitations
      if (player.x - player.w / 2 < 0) { player.x = player.w / 2 }
      if (player.x + player.w / 2 > sw) { player.x = sw - player.w / 2 }
      if (player.y - player.h / 2 < 0) { player.y = player.h / 2 }
      if (player.y + player.h / 2 > sh) { player.y = sh - player.h / 2 }
      //!Border limitations
      player.draw();
      requestAnimationFrame(controlMove);
    }
    controlMove();
    // ! Controls

What do I do about my functions referencing variables like player.x and player.y (while trying to maintain performance)?

And is it possible to initialize these event listeners somehow other than in the main file, to reduce clutter.

document.addEventListener('keydown', keyDownHandler, false);
document.addEventListener('keyup', keyUpHandler, false);

Upvotes: 1

Views: 914

Answers (1)

Karl Johan Vallner
Karl Johan Vallner

Reputation: 4300

1st of all, use the OnPush change detection strategy. Especially in a game in which you want to optimize performance.

@Component({
  selector: 'app-game-screen',
  templateUrl: './game-screen.component.html',
  styleUrls: ['./game-screen.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class GameScreenComponent implements OnInit {

This might require you to trigger change detection yourself on some occasions, so you better have a look at this article, which explains it.

https://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html

If you want to separate the controls into a separate file, then you should probably just make a one singleton service (aka. GameStore) that holds your player.x and player.y and other app wide data and then another service, which accesses GameStore-s player values, detects or waits for notification of keystrokes and handles them (aka. GameController).

I usually use Observables in my Stores, aka.

export class GameStoreService {

    private _player: BehaviorSubject<PlayerModel> = new BehaviorSubject(null);

    setPlayer( _player: PlayerModel ) {
        this._player.next( _player );
    }

    get player() {
        return this._player.asObservable();
    }
}

Which anyone can subscribe to and push to.

Concerning the listeners in anything other than the main file

document.addEventListener('keydown', keyDownHandler, false);
document.addEventListener('keyup', keyUpHandler, false);

Do use HostListeners for these, but you cannot set them in any file, I think this SO thread had a good explanation of what's going on

Is it possible to use HostListener in a Service?

Upvotes: 1

Related Questions