交通轨迹动画效果

代码语言:html

所属分类:动画

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">

<title> traffic</title>

</head>
<body translate="no">

<script>
      "use strict";

/* no street : they run everywhere
              */
window.addEventListener("load", function () {

  let canv, ctx;
  let sqSide;
  let nbx, nby; // nb of squares horiz. / vert.
  let terrain; // bi-dimensionnal array for car paths

  let cars;
  let blocked, veryVeryBlocked; // thresholds for blocking detection

  let carsMaxLength; // maximum length for cars
  let nbCars; // number of cars
  let initTime;
  let msByStep; // interval between 2 moves

  /********************************************************
  parameters - play with them
  ********************************************************/

  const bgColor = '#004'; // background color

  nbCars = 20; // number of cars

  /* an 'element' is a little square - a car id made of a few elements */
  carsMaxLength = 15; // cars max length (in elements, not pixels)
  nbx = 50; // width (in elements)
  msByStep = 100; // ms between 2 moves

  blocked = 2 * carsMaxLength; // threshold for blocking detection
  veryVeryBlocked = 3 * carsMaxLength; // threshold for blocking detection

  //********************************************************

  // shortcuts for Math
  const mrandom = Math.random;
  const mfloor = Math.floor;
  const mceil = Math.ceil;
  const mround = Math.round;
  const mabs = Math.abs;
  const mmin = Math.min;
  const mmax = Math.max;

  const mPI = Math.PI;
  const mPIS2 = Math.PI / 2;
  const m2PI = Math.PI * 2;
  const msin = Math.sin;
  const mcos = Math.cos;
  const matan2 = Math.atan2;

  const mhypot = Math.hypot;
  const msqrt = Math.sqrt;

  //------------------------------------------------------------------------
  // classe Car

  function Car(index) {

    /*
                         color
                         points = [[x,y],[x,y]..]
                         dir      0 1 2 3 = up right down left
                         index    identifier
                         ntci     nb of turns without moving
                         nbSteps    nb of steps to go ahead in a direction
                       
                       */
    let kx, ky, lum;

    //  lum = (index == 0) ? 70 : 30;
    lum = 60;
    this.color = `hsl(${alea(360)}, 100%, ${lum}%)`;

    this.size = intAlea(2, carsMaxLength + 1); // length in elements
    this.points = []; // to store "pieces" of a car
    this.dir = intAlea(4); // 0 1 2 3 = up right down left
    this.index = index; // identifier for car
    this.ntci = 0; // nb of turns without moving

    do {
      kx = intAlea(nbx); // choose a free cell
      ky = intAlea(nby);
    } while (terrain[ky][kx] != -1);

    terrain[ky][kx] = index;
    for (let kp = 0; kp < this.size; ++kp) {
      this.points[kp] = [kx, ky];
    } // for kp

    this.initNbSteps();

  } // function Car

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  Car.prototype.initNbSteps = function () {
    /* the direction beeing given by this.dir, computes the number of steps the car
                                           will go ahead. Normally, some random position between present position and the
                                           edge of the terrain in the given direction */

    let e1, e2;
    let [x, y] = this.points[0];

    switch (this.dir) {
      case 0:e1 = 0;e2 = y;break;
      case 1:e1 = x + 1;e2 = nbx;break;
      case 2:e1 = y + 1;e2 = nby;break;
      case 3:e1 = 0;e2 = x;break;}

    if (e2 <= e1) ++e2;
    this.nbSteps = intAlea(e2 - e1);

  }; // Car.prototype.initNbSteps

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  Car.prototype.move = function () {

    /* moves the car, if possible straightforward for nbSteps, avoiding collisions and
                                    using unblocking strategies */

    let x, y, kfront;

    this.ntci++; // count blockigg time a priori

    if (this.ntci > 2000) {// things are going very wrong
      console.dir(this);
      throw "blocked ! ";
    }

    /* is it time to change of direction ? */

    if (this.nbSteps < 0) {
      this.turn();
      return;
    }
    /* try to go ahead */
    [x, y] = this.futurePosition(this.dir);
    if (Car.ifOutOfTerrain(x, y)) {
      this.turn();
      return;
    } // if hit edge

    kfront = terrain[y][x];
    if (kfront == -1) {// free place, we can go
      this.moveOneStep();
      return;
    }
    // detect if front shock
    if (cars[kfront].points[0][0] == x &&
    cars[kfront].points[0][1] == y &&
    cars[kfront].dir == (this.dir + 2) % 4) {
      this.doUTurn();
      return;
    } // if front shock


    if (this.ntci > blocked) {// if waiting for too long
      this.turn(); // try to turn
      if (this.ntci > veryVeryBlocked) {// if waiting for really too long
        this.doUTurn(); // try U turn
      }
      return;
    }


  }; // Car.prototype.move

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  Car.ifOutOfTerrain = function (x, y) {
    /* tests if a cell is outside the terrain */

    return x < 0 || x >= nbx || y < 0 || y >= nby;

  }; // Car.ifOutOfTerrain

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  Car.prototype.futurePosition = function (dir) {
    /* evaluates futer place if we go towards the 'dir' direction */
    let x, y;
    x = this.points[0][0] + [0, 1, 0, -1][dir];
    y = this.points[0][1] + [-1, 0, 1, 0][dir];
    return [x, y];
  }; // Car.prototype.futurePosition

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  Car.prototype.turn = function () {
    /* change l'orientation de 90 degrés
                                    */

    let x, y;

    this.dir = (this.dir + 1 + 2 * intAlea(2)) % 4; // + ou - 1 randomly
    this.initNbSteps(); // nb of steps
    [x, y] = this.futurePosition(this.dir);
    if (Car.ifOutOfTerrain(x, y) || terrain[y][x] != -1) {
      this.dir = (this.dir + 2) % 4; // try the other side
      this.initNbSteps(); // nb de pas
      [x, y] = this.futurePosition(this.dir);
      if (Car.ifOutOfTerrain(x, y) || terrain[y][x] != -1) {
        return; // still blocked…
      } // if blocked
    } // if cannot on one side
    this.moveOneStep(); // Now we can go

  }; // Car.prototype.turn

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  Car.prototype.doUTurn = function () {

    /* reverts head and tail and moves one step */

    let x, y, xpre, ypre;

    let k1 = 0; // the first
    let k2 = this.points.length - 1; // the last

    /* the present head becomes tail : redraw it as a simple element */
    [x, y] = this.points[0];
    drawElement(x, y, this.color);

    for (; k1 < k2; ++k1, --k2) {// revert elements of car
      [this.points[k1], this.points[k2]] = [this.points[k2], this.points[k1]];
    }
    // evaluate new direction from first new two elements
    [x, y] = this.points[0];
    [xpre, ypre] = this.points[1];

    if (y < ypre) this.dir = 0; // up
    else if (x > xpre) this.dir = 1; // right
      else if (y > y.........完整代码请登录后点击上方下载按钮下载查看

网友评论0