public void compute() {
    for (int i = 0; i < bullet.size(); i++) {
      bullet.get(i).bullet_x = bullet.get(i).bullet_x + 3 * bullet.get(i).current_direction_x;
      bullet.get(i).bullet_y = bullet.get(i).bullet_y + 3 * bullet.get(i).current_direction_y;
    }
    for (int i = 0; i < bullet.size(); i++) {
      if (bullet.get(i).bullet_x > 1366
          || bullet.get(i).bullet_x < 0
          || bullet.get(i).bullet_y > 768
          || bullet.get(i).bullet_y < 0) bullet.remove(i);
    }
    // Check collision bullet with enemy
    for (int i = 0; i < bullet.size(); i++) {
      for (int j = 0; j < enemy.size(); j++) {
        if (collision.collision_bullet_enemy(
                18,
                (int) bullet.get(i).bullet_x + 18,
                (int) bullet.get(i).bullet_y + 18, // bullet
                (int) enemy.get(j).getX(),
                (int) enemy.get(j).getY(), // point x1, y1
                (int) enemy.get(j).getX() + (int) enemy.get(j).get_spr_w(),
                (int) enemy.get(j).getY(), // point x2, y2
                (int) enemy.get(j).getX() + (int) enemy.get(j).get_spr_w(),
                (int) enemy.get(j).getY() + (int) enemy.get(j).get_spr_h(),
                (int) enemy.get(j).getX(),
                (int) enemy.get(j).getY() + (int) enemy.get(j).get_spr_h() // point x4, y4
                )
            == true) {
          //	create_explosion(bullet.get(i).bullet_x, bullet.get(i).bullet_y);
          if (bullet.get(i).get_type() == 's') // simple bullet
          {
            enemy.get(j).dec_live();
          }
          if (bullet.get(i).get_type() == 'f') // fireball
          {
            enemy.get(j).dec_live();
            enemy.get(j).dec_live();
          }
          if (bullet.get(i).get_type() == 'r') // rocket
          {
            enemy.get(j).dec_live();
            enemy.get(j).dec_live();
            enemy.get(j).dec_live();
          }
          if (enemy.get(j).get_live() <= 0) {
            enemy.remove(j);
          } else // push enemy
          {
            enemy.get(j).push();
          }
          bullet.remove(i);
          break;
        }
      }
    }
    // Преследование игрока
    for (int i = 0; i < enemy.size(); i++) {
      if (enemy.get(i).get_type() == "enemy1"
          || enemy.get(i).get_type() == "enemy2"
          || enemy.get(i).get_type() == "enemy3") {
        angle2 =
            Math.atan2(player.getY() - enemy.get(i).getY(), player.getX() - enemy.get(i).getX())
                * 180
                / 3.14;
        double a = player.getX() - enemy.get(i).getX();
        double b = player.getY() - enemy.get(i).getY();
        double kvadrat = Math.sqrt((a * a + b * b));
        double tempx = a / kvadrat;
        double tempy = Math.sqrt(1 - tempx * tempx);
        if (b < 0) tempy = -tempy;
        enemy.get(i).v_x = enemy.get(i).speed * tempx;
        enemy.get(i).v_y = enemy.get(i).speed * tempy;
        enemy.get(i).setX((enemy.get(i).getX() + enemy.get(i).speed * tempx));
        enemy.get(i).setY((enemy.get(i).getY() + enemy.get(i).speed * tempy));
      } else {
        if (enemy.get(i).created == false) {
          angle2 =
              Math.atan2(player.getY() - enemy.get(i).getY(), player.getX() - enemy.get(i).getX())
                  * 180
                  / 3.14;
          double a = player.getX() - enemy.get(i).getX();
          double b = player.getY() - enemy.get(i).getY();
          double kvadrat = Math.sqrt((a * a + b * b));
          double tempx = a / kvadrat;
          double tempy = Math.sqrt(1 - tempx * tempx);
          if (b < 0) tempy = -tempy;
          enemy.get(i).v_x = enemy.get(i).speed * tempx;
          enemy.get(i).v_y = enemy.get(i).speed * tempy;
          enemy.get(i).created = true;
        }
        enemy.get(i).setX((enemy.get(i).getX() + enemy.get(i).get_vx()));
        enemy.get(i).setY((enemy.get(i).getY() + enemy.get(i).get_vy()));
      }
    }
    for (int j = 0; j < enemy.size(); j++) {
      if (collision.collision_with_box(
              (int) player.getX() + 14,
              (int) player.getY() + 28,
              (int) player.getX() + 114,
              (int) player.getY() + 95,
              (int) enemy.get(j).getX() + 22,
              (int) enemy.get(j).getY() + 30,
              (int) enemy.get(j).getX() + 102,
              (int) enemy.get(j).getY() + 96)
          == true) {
        enemy.remove(j);
        player_live--;
        if (player_live == 0) {
          JOptionPane.showMessageDialog(null, "Game over!");
          start_game();
        }
      }
    }
    if (time_game > frequency) {
      generate_enemy();
      time_game = 0;
    }
    if (left_mouse_pressed == true && allow_shoot == true) {}

    time_game += 0.01;
    frequency -= 0.0001;
  }
  private double[] calculatePenaltyForces(double[] X, double[] V, HashSet<Collision> cSet) {
    double[] penalty = new double[X.length];

    // for each collision, apply the penalties
    for (Collision col : cSet) {
      // Collision col = col_rec[i];
      // vertex-face collision
      if (col.getType() == Collision.VERTEX_FACE) {
        //	System.out.println("VERTEX-FACE");
        // get indicies
        int[] parts = col.getParticles();
        int p = parts[0];
        int a = parts[1];
        int b = parts[2];
        int c = parts[3];

        // get barycentric coords
        double[] bc = col.getBaryCoords();
        double u = bc[0];
        double v = bc[1];
        double w = bc[2];

        // get collision point and collision velocities
        Vector3d xa = new Vector3d(); // was Vector3d xa, xb, va, vb;
        Vector3d xb = new Vector3d();
        Vector3d va = new Vector3d();
        Vector3d vb = new Vector3d();

        xa.set(X[3 * p], X[3 * p + 1], X[3 * p + 2]);
        xb.set(
            u * X[3 * a] + v * X[3 * b] + w * X[3 * c],
            u * X[3 * a + 1] + v * X[3 * b + 1] + w * X[3 * c + 1],
            u * X[3 * a + 2] + v * X[3 * b + 2] + w * X[3 * c + 2]);
        va.set(V[3 * p], V[3 * p + 1], V[3 * p + 2]);
        vb.set(
            u * V[3 * a] + v * V[3 * b] + w * V[3 * c],
            u * V[3 * a + 1] + v * V[3 * b + 1] + w * V[3 * c + 1],
            u * V[3 * a + 2] + v * V[3 * b + 2] + w * V[3 * c + 2]);

        // System.out.println("REL VEL "+xa.minus(xb).dot(va.minus(vb))+" "+va+" "+vb+" "+xa+"
        // "+xb);
        // System.out.println("REL VEL2 "+xb.minus(xa).dot(vb.minus(va)));
        /*if the objects have do not have
        a seperating velocity, apply the
        local spring penalty */
        if (xa.minus(xb).dot(va.minus(vb)) < 0) {
          double[] local_penalty = springPenalty(xa, xb, col.getDistance());
          // apply to vertex
          penalty[3 * p] += local_penalty[0];
          penalty[3 * p + 1] += local_penalty[1];
          penalty[3 * p + 2] += local_penalty[2];

          // apply to triangle coordinates
          penalty[3 * a] += bc[0] * local_penalty[3];
          penalty[3 * a + 1] += bc[0] * local_penalty[4];
          penalty[3 * a + 2] += bc[0] * local_penalty[5];
          penalty[3 * b] += bc[1] * local_penalty[3];
          penalty[3 * b + 1] += bc[1] * local_penalty[4];
          penalty[3 * b + 2] += bc[1] * local_penalty[5];
          penalty[3 * c] += bc[2] * local_penalty[3];
          penalty[3 * c + 1] += bc[2] * local_penalty[4];
          penalty[3 * c + 2] += bc[2] * local_penalty[5];
        }
      }

      // edge-edge collision
      if (col.getType() == Collision.EDGE_EDGE) {
        // get indicies
        int[] parts = col.getParticles();
        int p1 = parts[0];
        int q1 = parts[1];
        int p2 = parts[2];
        int q2 = parts[3];

        // get barycentric coords
        double[] coords = col.getBaryCoords();
        double s = coords[0];
        double t = coords[1];

        Vector3d xa = new Vector3d(); // was Vector3d xa, xb, va, vb;
        Vector3d xb = new Vector3d();
        Vector3d va = new Vector3d();
        Vector3d vb = new Vector3d();

        // edge points
        xa.set(
            s * X[3 * p1] + (1 - s) * X[3 * q1],
            s * X[3 * p1 + 1] + (1 - s) * X[3 * q1 + 1],
            s * X[3 * p1 + 2] + (1 - s) * X[3 * q1 + 2]);
        xb.set(
            t * X[3 * p2] + (1 - t) * X[3 * q2],
            t * X[3 * p2 + 1] + (1 - t) * X[3 * q2 + 1],
            t * X[3 * p2 + 2] + (1 - t) * X[3 * q2 + 2]);

        // velocities
        va.set(
            s * V[3 * p1] + (1 - s) * V[3 * q1],
            s * V[3 * p1 + 1] + (1 - s) * V[3 * q1 + 1],
            s * V[3 * p1 + 2] + (1 - s) * V[3 * q1 + 2]);
        vb.set(
            t * V[3 * p2] + (1 - t) * V[3 * q2],
            t * V[3 * p2 + 1] + (1 - t) * V[3 * q2 + 1],
            t * V[3 * p2 + 2] + (1 - t) * V[3 * q2 + 2]);

        /*if the objects have do not have
        a seperating velocity, apply the
        local spring penalty */
        if (xa.minus(xb).dot(va.minus(vb)) < 0) {
          double[] local_penalty = springPenalty(xa, xb, col.getDistance());
          // apply penalty to first edge
          penalty[3 * p1] += s * local_penalty[0];
          penalty[3 * p1 + 1] += s * local_penalty[1];
          penalty[3 * p1 + 2] += s * local_penalty[2];
          penalty[3 * q1] += (1 - s) * local_penalty[0];
          penalty[3 * q1 + 1] += (1 - s) * local_penalty[1];
          penalty[3 * q1 + 2] += (1 - s) * local_penalty[2];
          // apply penalty to second edge
          penalty[3 * p2] += t * local_penalty[3];
          penalty[3 * p2 + 1] += t * local_penalty[4];
          penalty[3 * p2 + 2] += t * local_penalty[5];
          penalty[3 * q2] += (1 - t) * local_penalty[3];
          penalty[3 * q2 + 1] += (1 - t) * local_penalty[4];
          penalty[3 * q2 + 2] += (1 - t) * local_penalty[5];
        }
      }
    }

    return penalty;
  }