text: /**
  	A generic template for an enemy in the game.
  	Code by Rob Kleffner, 2011
  */
  
  Mario.Enemy = function(world, x, y, dir, type, winged) {
      this.GroundInertia = 0.89;
      this.AirInertia = 0.89;
      this.RunTime = 0;
      this.OnGround = false;
      this.MayJump = false;
      this.JumpTime = 0;
      this.XJumpSpeed = 0;
      this.YJumpSpeed = 0;
      this.Width = 4;
      this.Height = 24;
      this.DeadTime = 0;
      this.FlyDeath = false;
      this.WingTime = 0;
      this.NoFireballDeath = false;
  
      this.X = x;
      this.Y = y;
      this.World = world;
  
      this.Type = type;
      this.Winged = winged;
  
      this.Image = Enjine.Resources.Images["enemies"];
  
      this.XPicO = 8;
      this.YPicO = 31;
      this.AvoidCliffs = this.Type === Mario.Enemy.RedKoopa;
      this.NoFireballDeath = this.Type === Mario.Enemy.Spiky;
  
      this.YPic = this.Type;
      if (this.YPic > 1) {
          this.Height = 12;
      }
      this.Facing = dir;
      if (this.Facing === 0) {
          this.Facing = 1;
      }
  
      this.PicWidth = 16;
  };
  
  Mario.Enemy.prototype = new Mario.NotchSprite();
  
  Mario.Enemy.prototype.CollideCheck = function() {
      if (this.DeadTime !== 0) {
          return;
      }
  
      var xMarioD = Mario.MarioCharacter.X - this.X,
          yMarioD = Mario.MarioCharacter.Y - this.Y;
  
      if (xMarioD > -this.Width * 2 - 4 && xMarioD < this.Width * 2 + 4) {
          if (yMarioD > -this.Height && yMarioD < Mario.MarioCharacter.Height) {
              if (this.Type !== Mario.Enemy.Spiky && Mario.MarioCharacter.Ya > 0 && yMarioD <= 0 && (!Mario.MarioCharacter.OnGround || !Mario.MarioCharacter.WasOnGround)) {
                  Mario.MarioCharacter.Stomp(this);
                  if (this.Winged) {
                      this.Winged = false;
                      this.Ya = 0;
                  } else {
                      this.YPicO = 31 - (32 - 8);
                      this.PicHeight = 8;
  
                      if (this.SpriteTemplate !== null) {
                          this.SpriteTemplate.IsDead = true;
                      }
  
                      this.DeadTime = 10;
                      this.Winged = false;
  
                      if (this.Type === Mario.Enemy.RedKoopa) {
                          this.World.AddSprite(new Mario.Shell(this.World, this.X, this.Y, 0));
                      } else if (this.Type === Mario.Enemy.GreenKoopa) {
                          this.World.AddSprite(new Mario.Shell(this.World, this.X, this.Y, 1));
                      }
                  }
              } else {
                  Mario.MarioCharacter.GetHurt();
              }
          }
      }
  };
  
  Mario.Enemy.prototype.Move = function() {
      var i = 0,
          sideWaysSpeed = 1.75,
          runFrame = 0;
  
      this.WingTime++;
      if (this.DeadTime > 0) {
          this.DeadTime--;
  
          if (this.DeadTime === 0) {
              this.DeadTime = 1;
              for (i = 0; i < 8; i++) {
                  this.World.AddSprite(new Mario.Sparkle(this.World, ((this.X + Math.random() * 16 - 8) | 0) + 4, ((this.Y - Math.random() * 8) | 0) + 4, Math.random() * 2 - 1, Math.random() * -1, 0, 1, 5));
              }
              this.World.RemoveSprite(this);
          }
  
          if (this.FlyDeath) {
              this.X += this.Xa;
              this.Y += this.Ya;
              this.Ya *= 0.95;
              this.Ya += 1;
          }
          return;
      }
  
      if (this.Xa > 2) {
          this.Facing = 1;
      }
      if (this.Xa < -2) {
          this.Facing = -1;
      }
  
      this.Xa = this.Facing * sideWaysSpeed;
  
      this.MayJump = this.OnGround;
  
      this.XFlip = this.Facing === -1;
  
      this.RunTime += Math.abs(this.Xa) + 5;
  
      runFrame = ((this.RunTime / 20) | 0) % 2;
  
      if (!this.OnGround) {
          runFrame = 1;
      }
  
      if (!this.SubMove(this.Xa, 0)) {
          this.Facing = -this.Facing;
      }
      this.OnGround = false;
      this.SubMove(0, this.Ya);
  
      this.Ya *= this.Winged ? 0.95 : 0.85;
      if (this.OnGround) {
          this.Xa *= this.GroundInertia;
      } else {
          this.Xa *= this.AirInertia;
      }
  
      if (!this.OnGround) {
          if (this.Winged) {
              this.Ya += 0.6;
          } else {
              this.Ya += 2;
          }
      } else if (this.Winged) {
          this.Ya = -10;
      }
  
      if (this.Winged) {
          runFrame = ((this.WingTime / 4) | 0) % 2;
      }
  
      this.XPic = runFrame;
  };
  
  Mario.Enemy.prototype.SubMove = function(xa, ya) {
      var collide = false;
  
      while (xa > 8) {
          if (!this.SubMove(8, 0)) {
              return false;
          }
          xa -= 8;
      }
      while (xa < -8) {
          if (!this.SubMove(-8, 0)) {
              return false;
          }
          xa += 8;
      }
      while (ya > 8) {
          if (!this.SubMove(0, 8)) {
              return false;
          }
          ya -= 8;
      }
      while (ya < -8) {
          if (!this.SubMove(0, -8)) {
              return false;
          }
          ya += 8;
      }
  
      if (ya > 0) {
          if (this.IsBlocking(this.X + xa - this.Width, this.Y + ya, xa, 0)) {
              collide = true;
          } else if (this.IsBlocking(this.X + xa + this.Width, this.Y + ya, xa, 0)) {
              collide = true;
          } else if (this.IsBlocking(this.X + xa - this.Width, this.Y + ya + 1, xa, ya)) {
              collide = true;
          } else if (this.IsBlocking(this.X + xa + this.Width, this.Y + ya + 1, xa, ya)) {
              collide = true;
          }
      }
      if (ya < 0) {
          if (this.IsBlocking(this.X + xa, this.Y + ya - this.Height, xa, ya)) {
              collide = true;
          } else if (collide || this.IsBlocking(this.X + xa - this.Width, this.Y + ya - this.Height, xa, ya)) {
              collide = true;
          } else if (collide || this.IsBlocking(this.X + xa + this.Width, this.Y + ya - this.Height, xa, ya)) {
              collide = true;
          }
      }
  
      if (xa > 0) {
          if (this.IsBlocking(this.X + xa + this.Width, this.Y + ya - this.Height, xa, ya)) {
              collide = true;
          }
          if (this.IsBlocking(this.X + xa + this.Width, this.Y + ya - ((this.Height / 2) | 0), xa, ya)) {
              collide = true;
          }
          if (this.IsBlocking(this.X + xa + this.Width, this.Y + ya, xa, ya)) {
              collide = true;
          }
  
          if (this.AvoidCliffs && this.OnGround && !this.World.Level.IsBlocking(((this.X + this.Xa + this.Width) / 16) | 0, ((this.Y / 16) + 1) | 0, this.Xa, 1)) {
              collide = true;
          }
      }
      if (xa < 0) {
          if (this.IsBlocking(this.X + xa - this.Width, this.Y + ya - this.Height, xa, ya)) {
              collide = true;
          }
          if (this.IsBlocking(this.X + xa - this.Width, this.Y + ya - ((this.Height / 2) | 0), xa, ya)) {
              collide = true;
          }
          if (this.IsBlocking(this.X + xa - this.Width, this.Y + ya, xa, ya)) {
              collide = true;
          }
  
          if (this.AvoidCliffs && this.OnGround && !this.World.Level.IsBlocking(((this.X + this.Xa - this.Width) / 16) | 0, ((this.Y / 16) + 1) | 0, this.Xa, 1)) {
              collide = true;
          }
      }
  
      if (collide) {
          if (xa < 0) {
              this.X = (((this.X - this.Width) / 16) | 0) * 16 + this.Width;
              this.Xa = 0;
          }
          if (xa > 0) {
              this.X = (((this.X + this.Width) / 16 + 1) | 0) * 16 - this.Width - 1;
              this.Xa = 0;
          }
          if (ya < 0) {
              this.Y = (((this.Y - this.Height) / 16) | 0) * 16 + this.Height;
              this.JumpTime = 0;
              this.Ya = 0;
          }
          if (ya > 0) {
              this.Y = (((this.Y - 1) / 16 + 1) | 0) * 16 - 1;
              this.OnGround = true;
          }
  
          return false;
      } else {
          this.X += xa;
          this.Y += ya;
          return true;
      }
  };
  
  Mario.Enemy.prototype.IsBlocking = function(x, y, xa, ya) {
      x = (x / 16) | 0;
      y = (y / 16) | 0;
  
      if (x === (this.X / 16) | 0 && y === (this.Y / 16) | 0) {
          return false;
      }
  
      return this.World.Level.IsBlocking(x, y, xa, ya);
  };
  
  Mario.Enemy.prototype.ShellCollideCheck = function(shell) {
      if (this.DeadTime !== 0) {
          return false;
      }
  
      var xd = shell.X - this.X,
          yd = shell.Y - this.Y;
      if (xd > -16 && xd < 16) {
          if (yd > -this.Height && yd < shell.Height) {
              Enjine.Resources.PlaySound("kick");
  
              this.Xa = shell.Facing * 2;
              this.Ya = -5;
              this.FlyDeath = true;
              if (this.SpriteTemplate !== null) {
                  this.SpriteTemplate.IsDead = true;
              }
              this.DeadTime = 100;
              this.Winged = false;
              this.YFlip = true;
              return true;
          }
      }
      return false;
  };
  
  Mario.Enemy.prototype.FireballCollideCheck = function(fireball) {
      if (this.DeadTime !== 0) {
          return false;
      }
  
      var xd = fireball.X - this.X,
          yd = fireball.Y - this.Y;
      if (xd > -16 && xd < 16) {
          if (yd > -this.Height && yd < fireball.Height) {
              if (this.NoFireballDeath) {
                  return true;
              }
  
              Enjine.Resources.PlaySound("kick");
  
              this.Xa = fireball.Facing * 2;
              this.Ya = -5;
              this.FlyDeath = true;
              if (this.SpriteTemplate !== null) {
                  this.SpriteTemplate.IsDead = true;
              }
              this.DeadTime = 100;
              this.Winged = false;
              this.YFlip = true;
              return true;
          }
      }
  };
  
  Mario.Enemy.prototype.BumpCheck = function(xTile, yTile) {
      if (this.DeadTime !== 0) {
          return;
      }
  
      if (this.X + this.Width > xTile * 16 && this.X - this.Width < xTile * 16 + 16 && yTile === ((this.Y - 1) / 16) | 0) {
          Enjine.Resources.PlaySound("kick");
  
          this.Xa = -Mario.MarioCharacter.Facing * 2;
          this.Ya = -5;
          this.FlyDeath = true;
          if (this.SpriteTemplate !== null) {
              this.SpriteTemplate.IsDead = true;
          }
          this.DeadTime = 100;
          this.Winged = false;
          this.YFlip = true;
      }
  };
  
  Mario.Enemy.prototype.SubDraw = Mario.NotchSprite.prototype.Draw;
  
  Mario.Enemy.prototype.Draw = function(context, camera) {
      var xPixel = 0,
          yPixel = 0;
  
      if (this.Winged) {
          xPixel = ((this.XOld + (this.X - this.XOld) * this.Delta) | 0) - this.XPicO;
          yPixel = ((this.YOld + (this.Y - this.YOld) * this.Delta) | 0) - this.YPicO;
  
          if (this.Type !== Mario.Enemy.RedKoopa && this.Type !== Mario.Enemy.GreenKoopa) {
              this.XFlip = !this.XFlip;
              context.save();
              context.scale(this.XFlip ? -1 : 1, this.YFlip ? -1 : 1);
              context.translate(this.XFlip ? -318 : 0, this.YFlip ? -238 : 0);
              context.drawImage(this.Image, (((this.WingTime / 4) | 0) % 2) * 16, 4 * 32, 16, 32,
                  this.XFlip ? (318 - xPixel - 24) : xPixel - 8, this.YFlip ? (238 - yPixel - 32) : yPixel - 8, 16, 32);
              context.restore();
              this.XFlip = !this.XFlip;
          }
      }
  
      this.SubDraw(context, camera);
  
      if (this.Winged) {
          xPixel = ((this.XOld + (this.X - this.XOld) * this.Delta) | 0) - this.XPicO;
          yPixel = ((this.YOld + (this.Y - this.YOld) * this.Delta) | 0) - this.YPicO;
  
          if (this.Type === Mario.Enemy.RedKoopa && this.Type === Mario.Enemy.GreenKoopa) {
              context.save();
              context.scale(this.XFlip ? -1 : 1, this.YFlip ? -1 : 1);
              context.translate(this.XFlip ? -318 : 0, this.YFlip ? -238 : 0);
              context.drawImage(this.Image, (((this.WingTime / 4) | 0) % 2) * 16, 4 * 32, 16, 32,
                  this.XFlip ? (318 - xPixel - 24) : xPixel - 8, this.YFlip ? (238 - yPixel) : yPixel - 8, 16, 32);
              context.restore();
          } else {
              context.save();
              context.scale(this.XFlip ? -1 : 1, this.YFlip ? -1 : 1);
              context.translate(this.XFlip ? -318 : 0, this.YFlip ? -238 : 0);
              context.drawImage(this.Image, (((this.WingTime / 4) | 0) % 2) * 16, 4 * 32, 16, 32,
                  this.XFlip ? (318 - xPixel - 24) : xPixel - 8, this.YFlip ? (238 - yPixel - 32) : yPixel - 8, 16, 32);
              context.restore();
          }
      }
  };
  
  //Static variables
  Mario.Enemy.RedKoopa = 0;
  Mario.Enemy.GreenKoopa = 1;
  Mario.Enemy.Goomba = 2;
  Mario.Enemy.Spiky = 3;
  Mario.Enemy.Flower = 4;