Larry
Larry

Reputation: 395

how is my variable changing to undefined Angular

Whenever I call moveAvatar(), this.vx and this.vy are are undefined.

How?

How it works in plain JS application:

Game starts: set an interval that calls draw() over and over, drawing on the canvas. I'm perplexed as to why this wouldn't work using typescript.

vx and vy are both defined, and assigned values. You can even print them out...

I literally ported this code from a pure JS application that works fine.

I have a feeling it has something to do with how angular treats intervals. Please let me know!! Thanks!

import {
  Component,
  OnInit
} from '@angular/core';

@Component({
  selector: 'app-avoid',
  templateUrl: './avoid.component.html',
  styleUrls: ['./avoid.component.css']
})
export class AvoidComponent implements OnInit {
  avatarImage;
  enemy;
  x = 30;
  y = 30;
  _x = 300;
  _y = 300;
  score = 0;
  vx: number = 0;
  vy: number = 0;
  scoreTracker;
  gameCanvas;
  frames;
  gameStatus = false;
  hud = {
    score: 0,
    left: 0,
    right: 0,
    up: 0,
    down: 0
  };
  backstage;
  time = 0;
  level = 1;
  enemySpeed = 0.5;
  levelTracker;

  constructor() {
  }

  ngOnInit() {
    let body = document.querySelector('body');
    body.addEventListener("keyup", this.moveAvatar);
    this.gameCanvas = document.getElementById("gameCanvas");
    this.scoreTracker = document.getElementById("score");
    this.levelTracker = document.getElementById('level');
    this.enemy = this.getEnemy();
    this.avatarImage = this.getAvatar();
  }

  levelUp() {
    this.level++;
    this.enemySpeed += 0.25;
    this.levelTracker.innerText = this.level.toString();
  }

  startCanvas() {
    this.backstage = document.createElement("canvas");
    this.backstage.width = this.gameCanvas.width;
    this.backstage.height = this.gameCanvas.height;
    if (this.frames != null) {
      this.gameOver();
    }
    this.backstage.getContext("2d", {
      alpha: false
    }).drawImage(this.avatarImage, this.x, this.y);
    this.backstage.getContext("2d", {
      alpha: false
    }).drawImage(this.enemy, this._x, this._y)
    this.gameCanvas.getContext("2d", {
      alpha: false
    }).drawImage(this.backstage, 0, 0);

    this.time = 0;

    const that = this;
    this.frames = setInterval(() => {
      that.Draw();
    }, 100);
  }

  getAvatar() {
    var avatarImage = new Image(30, 30);
    avatarImage.src = "../assets/images/avatar.png";
    return avatarImage;
  }

  getEnemy() {
    var enemy = new Image();
    enemy.src = "../assets/images/enemy.png"
    return enemy;
  }

  moveAvatar(key) {
    switch (key.keyCode) {
      case 37:
        this.vx--;
        break;
      case 38:
        this.vy--;
        break;
      case 39:
        this.vx++;
        break;
      case 40:
        this.vy++;
        break;
    }
  }

  Follow() {
    if (this.x > this._x) {
      this._x += this.enemySpeed;
    } else if (this.x < this._x) {
      this._x -= this.enemySpeed;
    }

    if (this.y > this._y) {
      this._y += this.enemySpeed;
    } else if (this.y < this._y) {
      this._y -= this.enemySpeed;
    }
  }

  Draw() {
    this.time++;

    this.Accelerate();
    this.Follow();

    if (this.x < 0 || this.y < 0 || this.y > 520 || this.x > 770) {
      this.gameOver();
      return;
    }

    this.score += 1;
    this.scoreTracker.value = this.score;
    this.backstage.width += 0;
    this.gameCanvas.width += 0;
    this.backstage.getContext("2d", {
      alpha: false
    }).drawImage(this.avatarImage, this.x, this.y);

    this.backstage.getContext("2d", {
      alpha: false
    }).drawImage(this.enemy, this._x, this._y);
    this.gameCanvas.getContext("2d", {
      alpha: false
    }).drawImage(this.backstage, 0, 0);
    if (this.x <= this._x + 20 && this.x >= this._x - 20) {
      if (this.y <= this._y + 20 && this.y >= this._y - 20) {
        this.gameOver();
      }
    }
    if (this.score % 500 === 0) {
      this.levelUp();
    }
  }

  Accelerate() {
    this.x += this.vx;
    this.y += this.vy;
  }

  gameOver() {
    clearInterval(this.frames);
    this.x = 30;
    this.y = 30;
    this._x = 300;
    this._y = 300;
    this.score = 0;
    this.scoreTracker.value = 0;
    this.level = 1;
    this.enemySpeed = 0.5;
    this.levelTracker.innerText = "1";
  }
}

Upvotes: 1

Views: 300

Answers (2)

KiraAG
KiraAG

Reputation: 783

Alternative to above correct answer, you can also use Renderer module to achieve the same. this.renderer.listen('keyup', target, callbackfn); Instead of manually adding the listeners, you let angular create and destroy the listeners.

Upvotes: 1

Sheik Althaf
Sheik Althaf

Reputation: 1605

call it like this

body.addEventListener('keyup', (ev) => this.moveAvatar(ev));

(OR)

body.addEventListener('keyup', this.moveAvatar.bind(this));

Upvotes: 3

Related Questions