Init = function()
  require("lib/bxeGeneral")
  require("lib/bxeMath")
  gDBG = nil
  _drawClass = Drawer()
  bounds = {
    -0.666,
    0.666
  }
  gPos = {
    0,
    0
  }
  gSkills = {
    0,
    0,
    0,
    0,
    0,
    0,
    0,
    0
  }
  gPoints = 25
  gPointsUsed = 0
  gPointCoef = 1.5
end
KeyHappen = function(inVal, inDown)
  return _drawClass:KeyHappen(inVal, inDown)
end
Draw = function(t, dt)
  return _drawClass:Draw(t, dt)
end
OnError = function()
  return _drawClass:OnError()
end
local Debug
Debug = function(inVal)
  gDBG = inVal
end
local TitleScreen
do
  local _base_0 = {
    KeyHappen = function(self, inVal, inDown)
      local stat = 0
      if (inVal == 6 and inDown == 1) then
        if self.showInst == 1 then
          self.showInst = 0
        else
          if self.curact == 1 then
            stat = self.curact
          end
          if self.curact == 2 then
            self.showInst = 1
          end
        end
      end
      return stat
    end,
    Activate = function(self)
      SetMouseVis(1)
      SetMouseFree(1)
      self.showInst = 0
    end,
    Draw = function(self, t, dt, fadeIn, fadeOut)
      local mouseX, mouseY = GetMouseScalar()
      Blend(1)
      local txts = {
        'Play!',
        'Instructions',
        'Exit'
      }
      local poss = {
        0,
        -0.3,
        -0.6
      }
      self.curact = 0
      Color(1)
      Push()
      Blend(0)
      Geom(0)
      Tex('background')
      Geom(0)
      Pop()
      Blend(0)
      for i = 0, 1 do
        Push()
        Scale(1.1, 1, 1)
        Scale(1 - 2 * i, 1, 1)
        Move(-0.84, 0, 0)
        Scale(0.15, 1, 1)
        Color(0, 0, 0, 1)
        Tex('grad')
        Geom(0)
        Pop()
      end
      Tex('bloodcell')
      Color(1)
      local bloodps = {
        {
          1,
          3
        },
        {
          -1,
          2.5
        },
        {
          0.5,
          0
        },
        {
          -1.5,
          -1
        },
        {
          2,
          0.5
        },
        {
          2,
          -2
        }
      }
      for i, v in ipairs(bloodps) do
        Push()
        Scale(0.2)
        Move(v[1], v[2], 0)
        Rotate(0.3 * t * sin(0.7 * i))
        Geom(0)
        Pop()
      end
      local wTexs = {
        'crazyvvirus',
        'virusnoglow'
      }
      for i = 0, 3 do
        Push()
        Scale(0.1)
        Scale(1.1 + 0.2 * sin(t * 2 + .3))
        Move(4 * (-1 + 2 * int(i * 0.5)), 3 * (-1.5 + 2.5 * (i % 2)), 5)
        Tex(0)
        for i = 1, 20 do
          Push()
          Blend(1)
          Debug('v1HSLA')
          HSLA(3, 1, 0.5, 0.5)
          Color(0, 0.2, 0.5, 0.3)
          Scale(0.8)
          Scale(0.8 + 0.2 * sin(t * 3.5 + 0.3))
          Rotate(0.4 * i + 0.3 * t)
          Move(1)
          Geom(0)
          Pop()
        end
        Blend(0)
        Rotate(0.3 * t * sin(i * 1.8))
        Tex('crazyvirus')
        Geom(0)
        Color(1, 1, 1, 1)
        Geom(0)
        Pop()
      end
      Push()
      Scale(fadeIn)
      Scale(1 + 3 * fadeOut)
      Rotate(fadeOut * fadeOut * 8)
      for i = 1, 3 do
        Blend(1)
        local dist = distance2({
          mouseX,
          mouseY
        }, {
          0,
          poss[i]
        })
        local glow = max(0, 1 - 3 * dist)
        if (dist < 0.1) then
          self.curact = i
        end
        Push()
        Move(0, poss[i], 0)
        Scale(0.1)
        Scale(max(1, 1.4 - dist * 2))
        Tex('font')
        for j = 1, 30 do
          Push()
          Rotate(0.3 * t * 2 + 0.03 * j + 0.5 * sin(0.1 * j - 2 * t))
          Debug('v2HSLA' .. t)
          HSLA(mod(0.1 + 0.03 * j + t, 1.0), 1, 0.5, 0.2 * glow)
          Scale(1.5 + 0.4 * sin(t * 3 + 0.3 * j))
          Tex('font')
          Text(txts[i], 0)
          Move(-0)
          Tex(0)
          Geom(0)
          Pop()
        end
        Push()
        Scale(8, 0.2, 1)
        Debug('v3Color' .. t)
        Color(1, 1, 1, 0.3 * glow * (0.6 + 0.5 * sin(2 * t)))
        Move(0, 0.4 * sin(0.5 * t), 0)
        Rotate(sin(0.2 * t) * 0.25)
        Geom(0)
        Pop()
        Blend(0)
        Color(1)
        if self.curact == i then
          Color(0, 1, 0, 1)
        end
        Tex('font')
        Text(txts[i], 0)
        Tex(-1)
        Pop()
      end
      Pop()
      Push()
      Blend(0)
      if (fadeOut > 0) then
        Blend(1)
      end
      Scale(2 + fadeOut)
      Color(fadeOut, fadeOut, fadeOut, 1 - (fadeIn - 1.3 * fadeOut))
      Tex(-1)
      Geom(0)
      Pop()
      if self.showInst == 1 then
        Tex(-1)
        Color(0, 0, 0, 0.85)
        Geom(0)
        local str = ''
        Tex('font')
        Move(-0.7, 0.0)
        Color(1)
        Scale(0.1)
        str = str .. 'You are a nanotech bot trying to remove\n'
        str = str .. 'viral bodies from inside a host. Your goal \n'
        str = str .. 'is to save the host by shooting as many\n'
        str = str .. 'viruses as possible while moving through\n'
        str = str .. 'the ciculatory system. Avoid being hit by\n'
        str = str .. 'viruses.  Earn and spend points to increase\n'
        str = str .. 'your ship\'s power.\n'
        str = str .. '\n'
        str = str .. 'Keyboard/Mouse Controls:\n'
        str = str .. '\n'
        str = str .. 'Left-click:     drop bomb\n'
        str = str .. 'Right-click:   toggle shooting\n'
        str = str .. 'A:                   move left\n'
        str = str .. 'D:                   move right\n'
        str = str .. 'Q:                   snap left \n'
        str = str .. 'E:                   snap right\n'
        str = str .. 'W:                   snap straight'
        Text(str)
      end
      return 0
    end
  }
  _base_0.__index = _base_0
  local _class_0 = setmetatable({
    __init = function(self)
      self.curact = -1
    end,
    __base = _base_0,
    __name = "TitleScreen"
  }, {
    __index = _base_0,
    __call = function(cls, ...)
      local _self_0 = setmetatable({}, _base_0)
      cls.__init(_self_0, ...)
      return _self_0
    end
  })
  _base_0.__class = _class_0
  TitleScreen = _class_0
end
local SkillScreen
do
  local _base_0 = {
    KeyHappen = function(self, inVal, inDown)
      if inVal >= 30 and inVal <= 31 and inDown > 0 then
        if int(gPoints) > 0 then
          local wIdx = inVal - 30 + 7
          gSkills[wIdx] = gSkills[wIdx] + 1
          gPoints = gPoints - 1.0
          gPointsUsed = gPointsUsed + 1
        end
      end
      if inVal >= 13 and inVal <= 18 and inDown > 0 then
        if int(gPoints) > 0 then
          local wIdx = inVal - 12
          gSkills[wIdx] = gSkills[wIdx] + 1
          gPoints = gPoints - 1.0
          gPointsUsed = gPointsUsed + 1
        end
      end
      if inVal == 4 then
        self.done = 1
      end
    end,
    Activate = function(self, t)
      self.done = 0
    end,
    Draw = function(self, t, dt)
      Tex(-1)
      Blend(0)
      Color(1)
      Tex('font')
      Push()
      Move(0, 0.8, 0)
      Scale(0.07)
      Text('You have ' .. int(gPoints) .. ' points to spend on skills.\nPress the number for the appropriate skill increase.\nPress space when done', 0)
      Pop()
      Push()
      Move(-0.6, 0.1, 0)
      Scale(0.07)
      local mvA = -1.5
      Text('(' .. tostring(gSkills[1]) .. ') Press 1 to add a point to your damage per bullet.')
      Move(0, mvA, 0)
      Text('(' .. tostring(gSkills[2]) .. ') Press 2 to add a point to your fire rate.')
      Move(0, mvA, 0)
      Text('(' .. tostring(gSkills[3]) .. ') Press 3 to add a point to your health regen rate.')
      Move(0, mvA, 0)
      Text('(' .. tostring(gSkills[4]) .. ') Press 4 to add a point to your bomb reload rate.')
      Move(0, mvA, 0)
      Text('(' .. tostring(gSkills[5]) .. ') Press 5 to add a point to your bomb radius.')
      Move(0, mvA, 0)
      Text('(' .. tostring(gSkills[6]) .. ') Press 6 to add a point to your turning angle.')
      Move(0, mvA, 0)
      Text('(' .. tostring(gSkills[7]) .. ') Press b to buy towards ship upgrade ( new ship at 20 ).')
      Move(0, mvA, 0)
      Text('(' .. tostring(gSkills[8]) .. ') Press n to add a point to your move speed.')
      Pop()
      local rval = 0
      if self.done == 1 then
        rval = 2
      end
      return rval
    end
  }
  _base_0.__index = _base_0
  local _class_0 = setmetatable({
    __init = function(self) end,
    __base = _base_0,
    __name = "SkillScreen"
  }, {
    __index = _base_0,
    __call = function(cls, ...)
      local _self_0 = setmetatable({}, _base_0)
      cls.__init(_self_0, ...)
      return _self_0
    end
  })
  _base_0.__class = _class_0
  SkillScreen = _class_0
end
do
  local _base_0 = {
    KeyHappen = function(self, inVal, inDown)
      self.lastStat = self.curScreen:KeyHappen(inVal, inDown)
    end,
    OnError = function(self)
      return print('error db out = ', gDBG)
    end,
    Draw = function(self, t, dt)
      Blend(0)
      Depth(0, 0)
      SetCam(2, 2)
      if self.lastStat == 1 then
        self.lastStat = 0
        self.curFadeOut = 0.001
        if gPoints > 0 then
          self.queuedScreen = self.skillScreen
        else
          self.queuedScreen = self.gameScreen
        end
      end
      self.curFadeIn = min(1, self.curFadeIn + dt / 3.0)
      if (self.curFadeOut > 0) then
        self.curFadeOut = self.curFadeOut + (dt / 3.0)
      end
      if (self.curFadeOut >= 1.0) then
        self.curScreen = self.queuedScreen
        self.curScreen:Activate(0)
        self.curFadeOut = 0
        self.curFadeIn = 0
      end
      local fi = self.curFadeIn
      local fo = self.curFadeOut
      local v = self.curScreen:Draw(t, dt, fi, fo)
      if (v > 0) then
        if (v == 1) then
          self.curScreen = self.skillScreen
        end
        if (v == 2) then
          self.curScreen = self.gameScreen
        end
        return self.curScreen:Activate(t)
      end
    end
  }
  _base_0.__index = _base_0
  local _class_0 = setmetatable({
    __init = function(self)
      AddGeom("geom/quad.obj")
      AddGeom("geom/cube.obj")
      AddGeom("geom/monkey.obj")
      AddTex("textures/dot.png")
      AddTex("textures/font.png")
      AddTex("textures/h/background.png")
      AddTex("textures/h/pilljet.png")
      AddTex("textures/h/crazyship.png")
      AddTex("textures/h/crazyshipO.png")
      AddTex("textures/h/dodger.png")
      AddTex("textures/jitterNeon.png")
      AddTex("textures/noiseNeon.png")
      self.titleScreen = TitleScreen()
      self.gameScreen = GameScreen()
      self.skillScreen = SkillScreen()
      self.curScreen = self.titleScreen
      self.lastStat = 0
      self.queuedScreen = nil
      self.curScreen:Activate(0)
      self.curFadeIn = 0
      self.curFadeOut = 0
    end,
    __base = _base_0,
    __name = "Drawer"
  }, {
    __index = _base_0,
    __call = function(cls, ...)
      local _self_0 = setmetatable({}, _base_0)
      cls.__init(_self_0, ...)
      return _self_0
    end
  })
  _base_0.__class = _class_0
  Drawer = _class_0
end
local DoDels
DoDels = function(tabl, indices)
  local n = #indices
  for i = n, 1, -1 do
    table.remove(tabl, indices[i])
  end
  while #indices > 0 do
    table.remove(indices, 1)
  end
end
local Enemy
do
  local _base_0 = {
    TakeDmg = function(self, inD)
      self.hp = self.hp - inD
      if self.wt == 3 and self.hp <= 0 then
        self.hitCell = self.hitCell + 1
      end
    end,
    Draw = function(self, t, dt)
      Debug('enemyd')
      local moveAmt = clamp(1 + self.pos[2], 0.2, 1)
      local sd = self.seed
      local useDist = max(0, 1.0 - 2.0 * distance2(gPos, self.pos))
      self.pos[1] = self.pos[1] + (dt * (gPos[1] - self.pos[1]) * self.attackPct * useDist)
      local _exp_0 = self.moveStyle
      if 0 == _exp_0 then
        self.pos[2] = self.pos[2] + (dt * self.ySpd)
        self.pos[1] = clamp(self.pos[1] + dt * self.xSpd, -0.6, 0.6)
        if (sin(10 * t + sd) * sin(4 * t - 1 - sd) > 0.5) then
          self.xSpd = moveAmt * 0.2 * sin(10.3 * t + sd * 3)
        end
      elseif 1 == _exp_0 then
        self.pos[1] = 0.9 * self.pos[1] + 0.1 * self.tarpos[1]
        self.pos[2] = 0.9 * self.pos[2] + 0.1 * self.tarpos[2]
        local warpSpd = 0.7
        if int(warpSpd * t + sd) ~= int(warpSpd * (t - dt) + sd) then
          self.tarpos[2] = self.tarpos[2] + self.ySpd
          self.tarpos[1] = clamp(self.pos[1] + rand(-0.3, 0.3) * moveAmt, -0.6, 0.6)
        end
      elseif 2 == _exp_0 then
        self.ySpd = -0.1 + 0.1 * sin(2.3 * t + sd)
        self.pos[2] = self.pos[2] + (dt * self.ySpd)
        self.xSpd = self.xSpd + (dt * sin(t - sd) * sin(1.6 * t - sd) * moveAmt)
        self.pos[1] = clamp(self.pos[1] + dt * self.xSpd, -0.6, 0.6)
      elseif 3 == _exp_0 then
        self.pos[2] = self.pos[2] + (dt * self.ySpd)
      elseif 4 == _exp_0 then
        self.pos[2] = self.pos[2] + (dt * self.ySpd)
        self.pos[1] = sin(01.3 * t + sd) * sin(0.42 * t - 1 + 4 * sd) * 0.5
      elseif 5 == _exp_0 then
        self.pos[2] = self.pos[2] + (dt * self.ySpd)
        self.pos[1] = sin(0.1 * t + sd) * 0.5
      end
      if self.pos[1] < 1.1 then
        if self.wt == 3 then
          Blend(1)
          Tex(0)
          Push()
          Scale(3)
          Debug('w1HSLA')
          HSLA(1, 0, 1, 0.5)
          Geom(0)
          Pop()
        end
        Color(1)
        if self.wt == 2 then
          Scale(5)
        end
        Blend(0)
        Tex(self.texn)
        Scale(1.1 + 0.2 * sin(1.5 * t + sd))
        if self.wt ~= 2 then
          Rotate(self.rspd * t + self.seed)
        end
        return Geom(0)
      end
    end
  }
  _base_0.__index = _base_0
  local _class_0 = setmetatable({
    __init = function(self, inType, inX, inY, inHPCoef)
      if inHPCoef == nil then
        inHPCoef = 1.0
      end
      self.wt = inType
      self.texn = 'virusnoglow'
      self.moveStyle = randint(0, 1)
      self.multPos = -10
      self.r = 0.05
      self.takesDmg = true
      self.hp = 1.7
      self.ySpd = -0.1
      self.rspd = 0.3
      self.hitCell = 0
      self.attackPct = 0.5
      self.hitDmg = 0.07
      self.heartDmg = 0.001 * 5.0
      self.points = 0.005
      if self.wt == 1 then
        self.texn = 'crazyvirus'
        self.moveStyle = 2
        self.r = 0.03
        self.multPos = 0
      end
      if self.wt == 2 then
        self.hp = 100
        self.r = 0.01
        self.takesDmg = false
        self.moveStyle = 3
        self.texn = 'dodger'
        self.ySpd = -0.9 * rand(0.3, 1.2)
        self.heartDmg = 0
        self.attackPct = 0
      end
      if self.wt == 3 then
        self.texn = 'bloodcell'
        self.ySpd = -0.4 * rand(0.5, 1.0)
        self.hp = 4.6
        self.moveStyle = 4
        self.hitDmg = 0
        self.heartDmg = 0
        self.points = 0.3
      end
      if self.wt == 4 then
        self.texn = 'boss1'
        self.ySpd = -0.1 * rand(0.5, 1.0)
        self.hp = 30.0
        self.moveStyle = 5
        self.r = 0.13
        self.rspd = 0.2
        self.hitDmg = 0.4
        self.heartDmg = 0.001 * 70.0
        self.points = 0.1
      end
      self.pos = {
        inX,
        inY
      }
      self.seed = rand(0, 100)
      self.enemyDmg = 0
      if (rand(0, 1) > 0.5) then
        self.rspd = self.rspd * -1
      end
      self.explodes = true
      if (self.moveStyle == 1) then
        self.ySpd = -0.2
      end
      self.xSpd = 0
      self.tarpos = {
        self.pos[1],
        self.pos[2]
      }
      self.hp = self.hp * inHPCoef
    end,
    __base = _base_0,
    __name = "Enemy"
  }, {
    __index = _base_0,
    __call = function(cls, ...)
      local _self_0 = setmetatable({}, _base_0)
      cls.__init(_self_0, ...)
      return _self_0
    end
  })
  _base_0.__class = _class_0
  Enemy = _class_0
end
local Explo
do
  local _parent_0 = Enemy
  local _base_0 = {
    Draw = function(self, t, dt)
      Debug('explod')
      self.tAudS = self.tAudS - dt
      if self.tAudS < 0 and self.tAudS + dt >= 0 then
        local au = Audio('shot')
        AudioProps(au, min(0.1, 0.03 + 0.1 * self.outDmg), self.pitch)
      end
      Tex('bubble')
      self.hp = self.hp - (0.9 * dt)
      Scale(min(1, 2 * self.hp) * min(1, 2 * (1 - self.hp)))
      Color(1, 1, 1, 0.4)
      Geom(0)
      Color(1)
      self.ttd = self.ttd - dt
      if self.ttd <= 0 then
        self.ttd = 100
        self.enemyDmg = self.outDmg
      end
    end
  }
  _base_0.__index = _base_0
  setmetatable(_base_0, _parent_0.__base)
  local _class_0 = setmetatable({
    __init = function(self, inX, inY, inDmg, inRad)
      _parent_0.__init(self, 0, inX, inY)
      self.takesDmg = false
      self.explodes = false
      self.r = inRad
      self.ttd = 0.2
      self.outDmg = inDmg
      self.hp = 1.0
      self.tAudS = rand(0, 0.1)
      self.pitch = rand(0.8, 1.3)
      if inDmg > 0 then
        self.pitch = 0.3
      end
    end,
    __base = _base_0,
    __name = "Explo",
    __parent = _parent_0
  }, {
    __index = function(cls, name)
      local val = rawget(_base_0, name)
      if val == nil then
        return _parent_0[name]
      else
        return val
      end
    end,
    __call = function(cls, ...)
      local _self_0 = setmetatable({}, _base_0)
      cls.__init(_self_0, ...)
      return _self_0
    end
  })
  _base_0.__class = _class_0
  if _parent_0.__inherited then
    _parent_0.__inherited(_parent_0, _class_0)
  end
  Explo = _class_0
end
do
  local _base_0 = {
    Activate = function(self, t)
      SetMouseVis(1)
      SetMouseFree(1)
      self.shipX = 0
      self.shipY = -0.9
      self.dirPress = {
        0,
        0
      }
      self.curSpd = 0
      self.curAng = 0
      self.shots = { }
      self.firing = 1
      self.lastFire = -1
      self.addCoef = 0
      self.explos = { }
      self.enemies = { }
      self.lastE = -1
      self.doSecondary = 0
      self.bombs = { }
      self.deathT = 0
      self.waves = { }
      self.mobCoef = 1.0
      insert(self.waves, {
        {
          3,
          3,
          4,
          0.3
        },
        1.0,
        2.0,
        12.0,
        0
      })
      insert(self.waves, {
        {
          0.8,
          0.6,
          8,
          0.2
        },
        1.0,
        3.0,
        5.0,
        0
      })
      insert(self.waves, {
        {
          8,
          2,
          1,
          0.3
        },
        1.0,
        0.9,
        10.0,
        0
      })
      insert(self.waves, {
        {
          0,
          0,
          0,
          1
        },
        1.0,
        0.5,
        15.0,
        30.0
      })
      insert(self.waves, {
        {
          4,
          4,
          4,
          1.5
        },
        1.0,
        3.0,
        22.0,
        60.0
      })
      insert(self.waves, {
        {
          6,
          6,
          14,
          1.5
        },
        1.0,
        2.0,
        33.0,
        120.0
      })
      self.nextWave = 3
      self.nextBCell = 5
      self.playerHP = 1.0
      self.heartHealth = 1.0
      self.deathAnim = 0
      self.deathDuration = 4.0
      self.startT = t
      self.curPoints = 0
      self.skDamage = 0.2 + 0.3 * sqrt(0.5 * gSkills[1])
      self.skFireReload = 0.1 * (15 / (15 + gSkills[2]))
      self.skRegenRate = 0.02 + 0.0031 * sqrt(25 * gSkills[3])
      self.skBombReload = 2.0 * (15 / (15 + gSkills[4]))
      self.skBombRadius = 0.2 + 0.25 * math.atan(0.2 * gSkills[5]) / PIhalf
      self.skTurnAngle = 0.5 + 0.4 * math.atan(0.3 * gSkills[6]) / PIhalf
      self.pointCoef = 0.14
      self.nextBomb = 0
      self.goodship = false
      if gSkills[7] >= 20 then
        self.goodship = true
      end
      self.skMoveSpd = 0.7 + 0.2 * sqrt(gSkills[8])
    end,
    AddEnemies = function(self, t)
      local curT = t - self.startT
      local lvlSpd = 1 + sqrt(0.13 * gPointsUsed)
      local coef = max(1.0, gPointsUsed * 0.15 + lvlSpd * 3.3 * (curT / 60.0)) + self.addCoef
      self.mobCoef = coef * 0 + 2.0
      coef = coef + 1.5
      local mobNCoef = sqrt(2 * min(15, coef))
      local hpCoef = 1.0
      if (coef > 15) then
        hpCoef = 1.0 + (coef - 15) * 0.14
      end
      local taddCoef = clamp(1.0 - 0.05 * coef, 0.3, 1.0)
      if t >= self.nextWave then
        local wave = self.waves[randint(1, #self.waves)]
        while (wave[5] > t) do
          wave = self.waves[randint(1, #self.waves)]
        end
        local wEn = wave[1]
        for i = 1, #wEn do
          local n = int(wEn[i] * mobNCoef)
          for j = 1, n do
            local ei = i - 1
            if ei >= 3 then
              ei = ei + 1
            end
            self.enemies[#self.enemies + 1] = Enemy(ei, rand(-0.6, 0.6) * wave[2], 1.09 + wave[3] * rand(0, 1), hpCoef)
          end
        end
        self.nextWave = t + wave[4] * taddCoef
      end
      if t >= self.nextBCell then
        self.nextBCell = t + rand(7.0, 13.0)
        self.enemies[#self.enemies + 1] = Enemy(3, rand(-0.5, 0.5), 1.09)
      end
    end,
    KeyHappen = function(self, inVal, inDown)
      Debug('keyhap')
      if inDown < 2 then
        if (inVal == 2 or inVal == 3) then
          self.dirPress[inVal - 1] = inDown
        end
        if (inVal == 7 and inDown == 1) then
          self.lastFire = -1
        end
      end
      if inDown == 1 then
        if inVal == 0 then
          self.curAng = 0
        end
        if inVal == 20 then
          self.curAng = max(-self.skTurnAngle, self.curAng - self.skTurnAngle * 0.5)
        end
        if inVal == 21 then
          self.curAng = min(self.skTurnAngle, self.curAng + self.skTurnAngle * 0.5)
        end
        if inVal == 6 then
          self.doSecondary = 1
        end
        if inVal == 4 then
          self.addCoef = self.addCoef + 1
        end
      end
      return 0
    end,
    Draw = function(self, t, dt, fadeIn, fadeOut)
      Debug('draw')
      if self.deathAnim > 0 then
        self.deathAnim = self.deathAnim + dt
        dt = dt * (0.3 * max(0, 1 - 1.3 * self.deathAnim / self.deathDuration))
        self.deathT = self.deathT + dt
        t = self.deathT
      end
      local mouseX, mouseY = GetMouseTotal()
      mouseX, mouseY = GetMouseScalar()
      Push()
      Color(1)
      Scale(0.6666 + 0.3, 1, 1)
      Move(0, 2 * mod(-0.1 * t, 1.0), 0)
      Tex('background')
      Geom('quad')
      Move(0, 2, 0)
      Geom('quad')
      Pop()
      Color(1)
      Tex(-1)
      Debug('draw1')
      for i = 1, 130 do
        Push()
        local pct = i / 130.0 + 0.1 * t * (1.0 + 0.4 * sin(i))
        local aWave = max(0, -0.5 + 1.5 * sin(-1.5 * PI * pct + PI2 * t * 7.0 / 6.0))
        Move(0.4 * sin(i + 0.1 * t), 1.05 - 2.1 * mod(pct, 1.0), 0)
        Scale(0.04)
        Tex('bloodcellBlur')
        Debug('c1, alph:' .. aWave)
        Color(1, 1, 1.0, 0.23 + 0.5 * aWave)
        Debug('w1')
        Rotate(0.025 * t - 4 * i * i)
        Geom(0)
        Pop()
      end
      Tex(-1)
      Blend(0)
      for i = 0, 1 do
        Push()
        Scale(1 - 2 * i, 1, 1)
        Move(-0.84, 0, 0)
        Scale(0.15, 1, 1)
        Color(0, 0, 0, 1)
        Tex('grad')
        Geom(0)
        Pop()
      end
      self:AddEnemies(t)
      Debug('draw2')
      local curAudI = max(1, min(8, 1 + int(((#self.enemies - 50) / 300.0) * 7)))
      if curAudI ~= self.curBeatSpd and t >= self.nextSpdChange then
        self.nextSpdChange = t + 15.0
        self.curBeatSpd = curAudI
      else
        curAudI = self.curBeatSpd
      end
      local curBPM = 70 + (curAudI - 1) * 10
      for i = 1, 8 do
        self.beats[i][3] = 0.0
      end
      local tarA = 1.0
      if (self.deathAnim > 0) then
        tarA = 0
      end
      self.beats[curAudI][3] = tarA
      for i = 1, 8 do
        self.beats[i][2] = clamp(self.beats[i][2] - dt * 4 + 5 * dt * self.beats[i][3], 0, 1)
        AudioProps(self.beats[i][1], 0.5 * self.beats[i][2], 1, 1)
      end
      if self.firing == 1 and t - self.lastFire > self.skFireReload and self.playerHP > 0 then
        self.lastFire = t
        local sw = 0.035
        if self.goodship then
          sw = sw * 0
        end
        self.shots[#self.shots + 1] = {
          self.shipX + sw,
          self.shipY,
          sin(self.curAng) + 0 * self.curSpd,
          cos(self.curAng)
        }
        if not self.goodship then
          self.shots[#self.shots + 1] = {
            self.shipX - sw,
            self.shipY,
            sin(self.curAng) + 0 * self.curSpd,
            cos(self.curAng)
          }
        end
        if self.goodship then
          local ns = 1.2
          local ta = 0.1 + 0.15 * sin(0.4 * t)
          sw = 0.035 * 1.5
          local na = self.curAng + ta
          self.shots[#self.shots + 1] = {
            self.shipX + sw * 1,
            self.shipY,
            ns * sin(na) + 0 * self.curSpd,
            ns * cos(na)
          }
          na = self.curAng - ta
          self.shots[#self.shots + 1] = {
            self.shipX - sw * 1,
            self.shipY,
            ns * sin(na) + 0 * self.curSpd,
            ns * cos(na)
          }
        end
      end
      local bulSpd = 0.7 * 2.7
      local n = #self.shots
      local dels = { }
      Debug('draw3')
      Tex('bullet')
      if self.goodship then
        Blend(1)
        Tex('bulleta')
      end
      Color(1)
      for i = 1, n do
        local sh = self.shots[i]
        sh[1] = sh[1] + (dt * sh[3] * bulSpd)
        sh[2] = sh[2] + (dt * sh[4] * bulSpd)
        if (sh[1] <= bounds[1] * 0.99) then
          sh[3] = abs(sh[3])
        end
        if (sh[1] >= bounds[2] * 0.99) then
          sh[3] = -abs(sh[3])
        end
        Push()
        Move(sh[1], sh[2], 0)
        Scale(0.01 * 3)
        Geom(0)
        Pop()
        if (sh[2] > 1.03) then
          dels[#dels + 1] = i
        end
      end
      DoDels(self.shots, dels)
      Color(1)
      Blend(0)
      Debug('draw4')
      for i, e in ipairs(self.enemies) do
        Push()
        Move(e.pos[1], e.pos[2], 0)
        Scale(e.r)
        e:Draw(t, dt)
        Debug('endDrawE')
        Pop()
        if e.hitCell > 0 then
          self.playerHP = self.playerHP + 0.5
          self.heartHealth = self.heartHealth + 0.100
          e.hitCell = 0
        end
        if (e.pos[2] - e.r < -0.9) then
          local dist = distance2({
            gPos[1],
            gPos[2]
          }, e.pos)
          if (dist < 0.05 + e.r and e.hitDmg > 0) then
            e.hp = 0
            insert(self.explos, Explo(e.pos[1], e.pos[2], 0, 0.1))
            self.playerHP = self.playerHP - (e.hitDmg * 0)
            local wk = 'kapew'
            if (rand(0, 1) > 0.5) then
              wk = wk .. 'r'
            end
            local au = Audio(wk)
            AudioProps(au, 0.2, rand(0.7, 1.2))
          end
        end
        if e.hp <= 0 or e.pos[2] < -1.1 then
          insert(dels, i)
          if (e.hp <= 0) then
            local pointCoef = gPointCoef / (self.pointCoef * gPoints + 1)
            gPoints = gPoints + e.points * pointCoef
          end
          if e.pos[2] < -1.1 then
            self.heartHealth = self.heartHealth - (e.heartDmg * 0)
            self.heartHealth = clamp(self.heartHealth, 0, 1.0)
          end
          if e.explodes and e.pos[2] > -1.1 then
            insert(self.explos, Explo(e.pos[1], e.pos[2], 0, 0.1))
          end
        end
      end
      DoDels(self.enemies, dels)
      for i, e in ipairs(self.explos) do
        Push()
        Move(e.pos[1], e.pos[2], 0)
        Scale(e.r)
        e:Draw(t, dt)
        Pop()
        if e.hp <= 0 then
          insert(dels, i)
        end
      end
      DoDels(self.explos, dels)
      Debug('draw5')
      for i, e in ipairs(self.enemies) do
        if e.takesDmg then
          for i2, p in ipairs(self.shots) do
            if (e.pos[1] - e.r - 0.02 < p[1]) then
              local dist = distance2(p, e.pos)
              if dist <= e.r + 0.01 then
                e:TakeDmg(self.skDamage)
                dels[#dels + 1] = i2
              end
            end
          end
        end
      end
      DoDels(self.shots, dels)
      for i2, ex in ipairs(self.explos) do
        if ex.enemyDmg > 0 then
          for i, e in ipairs(self.enemies) do
            if e.takesDmg and e.pos[2] - e.r - ex.r <= ex.pos[2] then
              local dist = distance2(ex.pos, e.pos)
              if dist <= e.r + ex.r then
                e:TakeDmg(rand(0.2, 1.4) * ex.enemyDmg)
              end
            end
          end
          ex.enemyDmg = 0
        end
      end
      local spdMax = 0.5 * self.skMoveSpd
      local accel = 1.3 * self.skMoveSpd
      self.curSpd = clamp(self.curSpd + accel * dt * (-self.dirPress[1] + self.dirPress[2]), -spdMax, spdMax)
      self.shipX = clamp(self.shipX + dt * self.curSpd, bounds[1], bounds[2])
      if (self.shipX <= bounds[1] * 0.99) then
        self.curSpd = 0.5 * abs(self.curSpd)
      end
      if (self.shipX >= bounds[2] * 0.99) then
        self.curSpd = -0.5 * abs(self.curSpd)
      end
      gPos[1] = self.shipX
      gPos[2] = self.shipY
      Push()
      Move(self.shipX, self.shipY, 0)
      Debug('draw6')
      Scale(0.05)
      Color(1)
      Tex('pilljet')
      if self.goodship then
        Scale(1.5)
        Tex('crazyship')
        Rotate(0, 0, 1, 1)
      end
      Rotate(0, 0, -1, self.curAng / PI)
      if (self.deathAnim == 0) then
        Geom(0)
        if self.goodship then
          Blend(1)
          Debug('c2, time:' .. t)
          Color(1, 1, 1, 0.75 + 0.5 * sin(5 * t))
          Debug('w2')
          Tex('crazyshipO')
          Geom(0)
          Blend(0)
        end
      end
      Pop()
      Tex(-1)
      if (self.playerHP <= 0 or self.heartHealth <= 0) and self.deathAnim == 0 then
        self.deathAnim = 0.01
        self.deathT = t
      end
      Debug('draw7')
      self.playerHP = max(0, self.playerHP)
      if (self.playerHP > 0) then
        self.playerHP = min(1, self.playerHP + self.skRegenRate * dt)
      end
      local hpAlph = max(0.1, 0.8 - 2.0 * (-0.3 + -gPos[1]))
      Push()
      Move(-0.7, -0.9, 0)
      Debug('one of the others')
      Color(0, 0, 0, hpAlph - 0.1)
      Push()
      Scale(0.25, 0.05, 1)
      Geom(0)
      Color(1, 0, 0, hpAlph)
      Move(-0.9 * 1 * (1 - self.playerHP))
      Scale(0.9 * self.playerHP, 0.9, 1)
      Geom(0)
      Color(1, 1, 1, hpAlph + 0.2)
      Pop()
      Tex('font')
      Scale(0.08)
      Text('hp: ' .. int(100 * self.playerHP), 0)
      Move(-6)
      local pointCoef = gPointCoef / (self.pointCoef * gPoints + 1)
      Text('lvl: ' .. tostring(int(10.0 * self.mobCoef) * 0.1) .. '\npoints: ' .. tostring(int(100.0 * gPoints) * 0.01) .. '\nPt Amt: ' .. tostring(int(100 * pointCoef) / 100.0), 0)
      Pop()
      Debug('draw8')
      Tex(-1)
      local hhAlph = max(0.1, 0.8 - 2.0 * (-0.3 + gPos[1]))
      Push()
      Move(0.7, -0.9, 0)
      Color(0, 0, 0, hhAlph - 0.1)
      Push()
      Scale(0.25, 0.05, 1)
      Geom(0)
      Color(0.8, 0.8, 0.8, hhAlph)
      Move(-0.9 * 1 * (1 - self.heartHealth))
      Scale(0.9 * self.heartHealth, 0.9, 1)
      Geom(0)
      Color(1, 1, 1, hhAlph + 0.2)
      Pop()
      Push()
      Tex('font')
      Scale(0.08)
      Text('heart: ' .. tostring(int(1000 * self.heartHealth)), 0)
      Pop()
      Move(0.13, 0.17, 0)
      Tex('heart')
      local v = 0.5 * (1 + sin(t * PI * 2 * curBPM / 60.0))
      Scale(0.09 + 0.03 * v * v)
      local lum = 0.7 + pow(v, 1.4) * 0.3
      Color(lum, lum, lum, hhAlph)
      Geom(0)
      Pop()
      Debug('draw9')
      Push()
      Move(mouseX, mouseY, 0)
      Scale(self.skBombRadius)
      Tex(0)
      local av = 0.3 + 0.2 * sin(t * 5)
      Color(av, 1, av, 0.4)
      if t >= self.nextBomb then
        Geom(0)
      end
      Pop()
      Debug('w3')
      if self.doSecondary == 1 then
        self.doSecondary = 0
        if t >= self.nextBomb then
          local bombCost = 0.07
          local addT = 1.0
          if self.goodship then
            bombCost = 0.09
            addT = 0.8
            insert(self.bombs, {
              mouseX - 0.2,
              mouseY,
              1
            })
            insert(self.bombs, {
              mouseX + 0.2,
              mouseY,
              1
            })
          else
            insert(self.bombs, {
              mouseX,
              mouseY,
              1
            })
          end
          self.playerHP = self.playerHP - bombCost
          self.nextBomb = t + self.skBombReload * addT
        end
      end
      Blend(0)
      for i, b in ipairs(self.bombs) do
        Push()
        Move(b[1], b[2], 0)
        b[3] = b[3] - (0.57 * dt)
        b[2] = b[2] - (0.05 * dt)
        local det = 1 - b[3]
        local tc = 1 + 5 * det * det
        Debug('c3, tc=' .. tc)
        Color(0.5 + 0.5 * sin(tc * 10))
        Debug('w4')
        Tex(0)
        Scale(0.03)
        Scale(0.5 + 0.5 * det)
        Geom(0)
        Color(1, 0, 0, 1)
        Tex('bubble')
        Geom(0)
        Pop()
        if (b[3] <= 0) then
          insert(dels, i)
          insert(self.explos, Explo(b[1], b[2], 5.0, self.skBombRadius))
        end
      end
      Debug('draw10')
      DoDels(self.bombs, dels)
      local retStat = 0
      if self.deathAnim > self.deathDuration then
        retStat = 1
      end
      if self.deathAnim > 0 then
        local p = 1.1 * self.deathAnim / self.deathDuration
        Blend(0)
        Tex(-1)
        Color(0, 0, 0, p)
        Geom(0)
      end
      return retStat
    end
  }
  _base_0.__index = _base_0
  local _class_0 = setmetatable({
    __init = function(self)
      AddTex('textures/h/virusnoglow.png')
      AddTex('textures/h/crazyvirus.png')
      AddTex('textures/h/bullet.png')
      AddTex('textures/h/bulleta.png')
      AddTex('textures/h/bloodcell.png')
      AddTex('textures/h/bloodcellBlur.png')
      AddTex('textures/h/boss1.png')
      AddTex('textures/h/heart.png')
      AddTex('textures/h/bubble.png')
      AddTex('textures/h/grad.png')
      AddAudio('audio/h/70bpm.wav')
      AddAudio('audio/h/80bpm.wav')
      AddAudio('audio/h/90bpm.wav')
      AddAudio('audio/h/100bpm.wav')
      AddAudio('audio/h/110bpm.wav')
      AddAudio('audio/h/120bpm.wav')
      AddAudio('audio/h/130bpm.wav')
      AddAudio('audio/h/140bpm.wav')
      AddAudio('audio/h/shot.wav')
      AddAudio('audio/negative.wav')
      AddAudio('audio/h/kapew.wav')
      AddAudio('audio/h/kapewr.wav')
      self.beats = { }
      for i = 0, 7 do
        insert(self.beats, {
          Audio(i),
          0,
          0
        })
        AudioProps(self.beats[i + 1][1], 0, 1, 1)
      end
      self.curBeatSpd = 1
      self.nextSpdChange = 0
      self.beats[1][3] = 1.0
      return AudioProps(self.beats[self.curBeatSpd][1], 1, 1, 1)
    end,
    __base = _base_0,
    __name = "GameScreen"
  }, {
    __index = _base_0,
    __call = function(cls, ...)
      local _self_0 = setmetatable({}, _base_0)
      cls.__init(_self_0, ...)
      return _self_0
    end
  })
  _base_0.__class = _class_0
  GameScreen = _class_0
  return _class_0
end
