text: import "phaser";
  import Food from '../assets/food.png';
  import Body from '../assets/body.png';
  
  var snake;
  var food;
  var cursors;
  
  //var ctx = new AudioContext();
  
  //  Direction consts
  var UP = 0;
  var DOWN = 1;
  var LEFT = 2;
  var RIGHT = 3;
  
  export default class Gamescene extends Phaser.Scene {
      constructor() {
          super('Game');
      }
  
      preload() {
          this.load.image("food", Food);
          this.load.image("body", Body);
      }
  
      create() {
          var Food = new Phaser.Class({
  
              Extends: Phaser.GameObjects.Image,
  
              initialize:
  
                  function Food(scene, x, y) {
                      Phaser.GameObjects.Image.call(this, scene)
  
                      this.setTexture('food');
                      this.setPosition(x * 16, y * 16);
                      this.setOrigin(0);
  
                      this.total = 0;
  
                      this.eatEffect = {
                          frequency: 523.25,
                          attack: 0.05,
                          decay: 0.2,
                          type: 'sine',
                          volume: 3,
                          pan: 0.8,
                          pitchBend: 600,
                          reverse: true,
                          random: 100
                      };
  
                      scene.children.add(this);
                  },
  
              eat: function () {
                  this.total++;
  
                  //new Phaser.Sound.Dynamic.FX(ctx, this.eatEffect);
              }
  
          });
  
          var Snake = new Phaser.Class({
  
              initialize:
  
                  function Snake(scene, x, y) {
                      this.headPosition = new Phaser.Geom.Point(x, y);
  
                      this.body = scene.add.group();
  
                      this.head = this.body.create(x * 16, y * 16, 'body');
                      this.head.setOrigin(0);
  
                      this.alive = true;
  
                      this.speed = 100;
  
                      this.moveTime = 0;
  
                      this.tail = new Phaser.Geom.Point(x, y);
  
                      this.heading = RIGHT;
                      this.direction = RIGHT;
  
                      this.deathEffect = {
                          frequency: 16,
                          decay: 1,
                          type: 'sawtooth',
                          dissonance: 50
                      };
                  },
  
              update: function (time) {
                  if (time >= this.moveTime) {
                      return this.move(time);
                  }
              },
              faceLeft: function () {
                  if (this.direction === UP || this.direction === DOWN) {
                      this.heading = LEFT;
                  }
              },
              faceRight: function () {
                  if (this.direction === UP || this.direction === DOWN) {
                      this.heading = RIGHT;
                  }
              },
  
              faceUp: function () {
                  if (this.direction === LEFT || this.direction === RIGHT) {
                      this.heading = UP;
                  }
              },
  
              faceDown: function () {
                  if (this.direction === LEFT || this.direction === RIGHT) {
                      this.heading = DOWN;
                  }
              },
              move: function (time) {
                  /**
                  * Based on the heading property (which is the direction the pgroup pressed)
                  * we update the headPosition value accordingly.
                  * 
                  * The Math.wrap call allow the snake to wrap around the screen, so when
                  * it goes off any of the sides it re-appears on the other.
                  */
                  switch (this.heading) {
                      case LEFT:
                          this.headPosition.x = Phaser.Math.Wrap(this.headPosition.x - 1, 0, 40);
                          break;
  
                      case RIGHT:
                          this.headPosition.x = Phaser.Math.Wrap(this.headPosition.x + 1, 0, 40);
                          break;
  
                      case UP:
                          this.headPosition.y = Phaser.Math.Wrap(this.headPosition.y - 1, 0, 30);
                          break;
  
                      case DOWN:
                          this.headPosition.y = Phaser.Math.Wrap(this.headPosition.y + 1, 0, 30);
                          break;
                  }
  
                  this.direction = this.heading;
  
                  //  Update the body segments and place the last coordinate into this.tail
                  Phaser.Actions.ShiftPosition(this.body.getChildren(), this.headPosition.x * 16, this.headPosition.y * 16, 1, this.tail);
  
                  //  Check to see if any of the body pieces have the same x/y as the head
                  //  If they do, the head ran into the body
  
                  var hitBody = Phaser.Actions.GetFirst(this.body.getChildren(), { x: this.head.x, y: this.head.y }, 1);
  
                  if (hitBody) {
                      console.log('dead');
  
                      //  Game Over
                      //new Phaser.Sound.Dynamic.FX(ctx, this.deathEffect);
  
                      this.alive = false;
  
                      return false;
                  }
                  else {
                      //  Update the timer ready for the next movement
                      this.moveTime = time + this.speed;
  
                      return true;
                  }
              },
  
              grow: function () {
                  var newPart = this.body.create(this.tail.x, this.tail.y, 'body');
  
                  newPart.setOrigin(0);
              },
  
              collideWithFood: function (food) {
                  if (this.head.x === food.x && this.head.y === food.y) {
                      this.grow();
  
                      food.eat();
  
                      //  For every 5 items of food eaten we'll increase the snake speed a little
                      if (this.speed > 20 && food.total % 5 === 0) {
                          this.speed -= 5;
                      }
  
                      return true;
                  }
                  else {
                      return false;
                  }
              },
  
              updateGrid: function (grid) {
                  //  Remove all body pieces from valid positions list
                  this.body.children.each(function (segment) {
  
                      var bx = segment.x / 16;
                      var by = segment.y / 16;
  
                      grid[by][bx] = false;
  
                  });
  
                  return grid;
              }
  
          });
  
          food = new Food(this, 3, 4);
  
          snake = new Snake(this, 8, 8);
  
          //  Create our keyboard controls
          cursors = this.input.keyboard.createCursorKeys();
      }
  
      update(time, delta) {
          if (!snake.alive) {
              return;
          }
          /**
     * Check which key is pressed, and then change the direction the snake
     * is heading based on that. The checks ensure you don't double-back
     * on yourself, for example if you're moving to the right and you press
     * the LEFT cursor, it ignores it, because the only valid directions you
     * can move in at that time is up and down.
     */
          if (cursors.left.isDown) {
              snake.faceLeft();
          }
          else if (cursors.right.isDown) {
              snake.faceRight();
          }
          else if (cursors.up.isDown) {
              snake.faceUp();
          }
          else if (cursors.down.isDown) {
              snake.faceDown();
          }
  
          if (snake.update(time)) {
              //  If the snake updated, we need to check for collision against food
  
              if (snake.collideWithFood(food)) {
                  repositionFood();
              }
  
          }
      }
  }
  
  /**
  * We can place the food anywhere in our 40x30 grid
  * *except* on-top of the snake, so we need
  * to filter those out of the possible food locations.
  * If there aren't any locations left, they've won!
  *
  * @method repositionFood
  * @return {boolean} true if the food was placed, otherwise false
  */
  function repositionFood() {
      //  First create an array that assumes all positions
      //  are valid for the new piece of food
  
      //  A Grid we'll use to reposition the food each time it's eaten
      var testGrid = [];
  
      for (var y = 0; y < 30; y++) {
          testGrid[y] = [];
  
          for (var x = 0; x < 40; x++) {
              testGrid[y][x] = true;
          }
      }
  
      snake.updateGrid(testGrid);
  
      //  Purge out false positions
      var validLocations = [];
  
      for (var y = 0; y < 30; y++) {
          for (var x = 0; x < 40; x++) {
              if (testGrid[y][x] === true) {
                  //  Is this position valid for food? If so, add it here ...
                  validLocations.push({ x: x, y: y });
              }
          }
      }
  
      if (validLocations.length > 0) {
          //  Use the RNG to pick a random food position
          var pos = Phaser.Math.RND.pick(validLocations);
  
          //  And place it
          food.setPosition(pos.x * 16, pos.y * 16);
  
          return true;
      }
      else {
          return false;
      }
  }
  