cannon+three打造一个三维小球重力下滑滑滑梯效果代码

代码语言:html

所属分类:三维

代码描述:cannon+three打造一个三维小球重力下滑滑滑梯效果代码

代码标签: 三维 小球 重力 滑滑 滑梯 效果

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

<!DOCTYPE html>
<html lang="en" >

<head>

  <meta charset="UTF-8">


 
  <style>
    :root {
      --tp-base-background-color: hsla(0, 0%, 40%, 1.00);
      --tp-base-shadow-color: hsla(0, 0%, 0%, 0.2);
      --tp-button-background-color: hsla(0, 0%, 100%, 1.00);
      --tp-button-background-color-active: hsla(0, 0%, 85%, 1.00);
      --tp-button-background-color-focus: hsla(0, 0%, 90%, 1.00);
      --tp-button-background-color-hover: hsla(0, 0%, 95%, 1.00);
      --tp-button-foreground-color: hsla(230, 20%, 11%, 1.00);
      --tp-container-background-color: hsla(0, 0%, 0%, 0.20);
      --tp-container-background-color-active: hsla(0, 0%, 0%, 0.35);
      --tp-container-background-color-focus: hsla(0, 0%, 0%, 0.30);
      --tp-container-background-color-hover: hsla(0, 0%, 0%, 0.25);
      --tp-container-foreground-color: hsla(0, 0%, 100%, 0.90);
      --tp-groove-foreground-color: hsla(0, 0%, 0%, 0.50);
      --tp-input-background-color: hsla(0, 0%, 0%, 0.50);
      --tp-input-background-color-active: hsla(0, 0%, 0%, 0.65);
      --tp-input-background-color-focus: hsla(0, 0%, 0%, 0.60);
      --tp-input-background-color-hover: hsla(0, 0%, 0%, 0.55);
      --tp-input-foreground-color: hsla(0, 0%, 100%, 0.90);
      --tp-label-foreground-color: hsla(0, 0%, 100%, 0.90);
      --tp-monitor-background-color: hsla(0, 0%, 0%, 0.50);
      --tp-monitor-foreground-color: hsla(0, 0%, 100%, 0.50);
    }

    html {
      font-family: 'Dosis', Arial, sans-serif;
      -ms-text-size-adjust: 100%;
      -webkit-text-size-adjust: 100%;
    }

    *,
    *::after,
    *::before {
      box-sizing: border-box;
    }

    body {
      padding: 0;
      margin: 0;
      background-color: #1c7dff;
      overflow: hidden;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      cursor: -moz-grabg;
      cursor: -webkit-grab;
    }

    .credits {
      position: absolute;
      z-index: 1;
      bottom: 0;
      width: auto;
      background-color: #07326b;
      padding: 10px;
      cursor: pointer;
      font-size: 8pt;
      font-weight: lighter;
    }

    .credits a {
      color: #ffffff;
      text-decoration: none;
    }

    .credits h1 {
      margin: inherit;
    }

    .credits:hover {
      background-color: #ff1111;
      color: #ffffff;
    }
  </style>

  
  
<style>
html {
  font-family: "Dosis", Arial, sans-serif;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
}

.stats {
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
}
</style>


</head>

<body>
  <div class="stats">
</div>

 
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/Stats-16.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/cannon.js"></script>

<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/three.126.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/OrbitControls.126.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/TransformControls.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/gsap.3.5.2.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/tweakpane.3.02.js"></script>

      <script >

class App {
  init() {
    this.setup();
    this.createScene();
    this.createCamera();
    this.addCameraControls();
    this.addAmbientLight();
    this.addDirectionalLight();
    this.addPhysicsWorld();
    this.addBackWall();
    this.addFloor();
    this.addWoodColumns();
    this.addRows();
    this.addEdges();
    this.addSphere();
    this.addFloorBox();
    this.addStatsMonitor();
    this.addWindowListeners();
    this.addGuiControls();
    this.addDummyCameraTarget();
    this.animateDummyCameraTarget();
    this.animate();
  }

  setup() {
    this.debug = false;
    this.width = window.innerWidth;
    this.height = window.innerHeight;
    this.cameraAutoAnimate = false;
    this.spheres = [];

    Sphere.loadTextures();
    Sphere.buildMaterial();
    Column.buildMaterial();
    Row.buildMaterial();
  }

  createScene() {
    this.scene = new THREE.Scene();
    this.scene.background = new THREE.Color(
    window.getComputedStyle(document.body).backgroundColor);

    this.renderer = new THREE.WebGLRenderer({ antialias: true });

    this.renderer.setSize(this.width, this.height);
    this.scene.position.set(0, -5, 0);
    this.renderer.shadowMap.enabled = true;
    this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;

    document.body.appendChild(this.renderer.domElement);
  }

  createCamera() {
    this.camera = new THREE.PerspectiveCamera(
    20,
    this.width / this.height,
    1,
    1000);

    this.camera.position.set(20, 20, 80);

    this.scene.add(this.camera);
  }

  addCameraControls() {
    this.orbitControl = new THREE.OrbitControls(
    this.camera,
    this.renderer.domElement);

    this.orbitControl.minPolarAngle = THREE.MathUtils.degToRad(0);
    this.orbitControl.maxPolarAngle = THREE.MathUtils.degToRad(90);
    this.orbitControl.minAzimuthAngle = THREE.MathUtils.degToRad(-50);
    this.orbitControl.maxAzimuthAngle = THREE.MathUtils.degToRad(50);
    this.orbitControl.maxDistance = 90;
    this.orbitControl.minDistance = 40;
    this.orbitControl.enableDamping = true;
    this.orbitControl.dampingFactor = 0.02;
    this.orbitControl.enablePan = !this.cameraAutoAnimate;
    this.orbitControl.enableRotate = !this.cameraAutoAnimate;
    this.orbitControl.enableZoom = !this.cameraAutoAnimate;
    this.orbitControl.saveState();

    this.orbitControl.addEventListener("start", () => {
      requestAnimationFrame(() => {
        document.body.style.cursor = "-moz-grabbing";
        document.body.style.cursor = "-webkit-grabbing";
      });
    });

    this.orbitControl.addEventListener("end", () => {
      requestAnimationFrame(() => {
        document.body.style.cursor = "-moz-grab";
        document.body.style.cursor = "-webkit-grab";
      });
    });
  }

  addPhysicsWorld() {
    this.physics = {
      fixedTimeStep: 1 / 60,
      maxSubSteps: 10,
      damping: 0.09,
      time: 0.01,
      lastTime: 0.01 };


    this.world = new CANNON.World();
    this.world.gravity.set(0, -120, 0);
    this.world.broadphase = new CANNON.NaiveBroadphase();
    this.world.solver.iterations = 10;
    this.world.defaultContactMaterial.contactEquationStiffness = 1e6;
    this.world.defaultContactMaterial.contactEquationRelaxation = 3;
    this.world.allowSleep = true;

    this.cannonDebugRenderer =
    this.debug &&
    new CannonDebugRenderer(this.scene, this.world, { THREE, CANNON });
  }

  addAmbientLight() {
    this.scene.add(new THREE.AmbientLight({ color: "#ffffff" }, 0.5));
  }

  addDirectionalLight() {
    this.directionalLight = new THREE.DirectionalLight("#ffffff", 0.8);
    this.directionalLight.castShadow = true;
    this.directionalLight.position.set(10, 15, 15);

    this.directionalLight.shadow.camera.needsUpdate = true;
    this.directionalLight.shadow.mapSize.width = 2048;
    this.directionalLight.shadow.mapSize.height = 2048;
    this.directionalLight.shadow.camera.left = -20;
    this.directionalLight.shadow.camera.right = 20;
    this.directionalLight.shadow.camera.top = 15;
    this.directionalLight.shadow.camera.bottom = -15;

    this.scene.add(this.directionalLight);
  }

  addFloor() {
    const geometry = new THREE.PlaneBufferGeometry(400, 150);
    const material = new THREE.MeshStandardMaterial({
      color: "#ffffff",
      side: THREE.DoubleSide });


    this.floor = new THREE.Mesh(geometry, material);
    this.floor.position.y = -5;
    this.floor.position.z = 0;
    this.floor.rotateX(Math.PI / 2);
    this.floor.receiveShadow = true;
    this.floor.body = new CANNON.Body({
      mass: 0,
      position: new CANNON.Vec3(0, this.floor.position.y, 0),
      material: new CANNON.Material(),
      shape: new CANNON.Plane(40, 40, 40) });


    this.floor.body.material.name = "floor";
    this.floor.body.quaternion.setFromAxisAngle(
    new CANNON.Vec3(1, 0, 0),
    THREE.MathUtils.degToRad(-90));

    this.world.addBody(this.floor.body);

    this.scene.add(this.floor);

    this.addFloorGrid();
  }

  addFloorGrid() {
    const size = 400;
    const divisions = size;
    const grid = new THREE.GridHelper(size, divisions, "#888888");

    grid.position.set(0, this.floor.position.y, 0);

    this.scene.add(grid);
  }

  addWoodColumns() {
    this.columnFront = new Column();
    this.columnFront.build();
    this.columnFront.mesh.position.y = 7;
    this.columnFront.mesh.position.z = 0.7;
    this.scene.add(this.columnFront.mesh);

    this.columnFront.cylinder.position.set(0, 0.2, 8.7);
    this.columnFront.mesh.add(this.columnFront.cylinder);

    const cylinder2 = this.columnFront.cylinder.clone();
    cylinder2.position.set(0, 0.2, 4);
    this.columnFront.mesh.add(cylinder2);

    const cylinder3 = this.columnFront.cylinder.clone();
    cylinder3.position.set(0, 0.2, -0.7);
    this.columnFront.mesh.add(cylinder3);

    const cylinder4 = this.columnFront.cylinder.clone();
    cylinder4.position.set(0, 0.2, -5.5);
    this.columnFront.mesh.add(cylinder4);

    const cylinder5 = this.columnFront.cylinder.clone();
    cylinder5.position.set(0, 0.2, -10.5);
    this.columnFront.mesh.add(cylinder5);

    this.columnBack = this.columnFront.mesh.clone();
    this.columnBack.position.y = this.columnFront.mesh.position.y;
    this.columnBack.position.z = -this.columnFront.mesh.position.z;

    this.scene.add(this.columnBack);
  }

  addRows() {
    this.row1 = new Row(this.world);
    this.row1.build({ size: 6 });
    this.row1.rotateZ(THREE.MathUtils.degToRad(-20));
    this.row1.position({ x: 2.2, y: 14, z: 0, gutter: -0.18 });
    this.scene.add(this.row1.mesh);

    this.row2 = new Row(this.world);
    this.row2.build({ size: 12 });
    this.row2.rotateZ(THREE.MathUtils.degToRad(10));
    this.row2.position({ x: 0.25, y: 10, z: 0, gutter: 0.1 });
    this.scene.add(this.row2.mesh);

    this.row3 = new Row(this.world);
    this.row3.build({ size: 12 });
    this.row3.rotateZ(THREE.MathUtils.degToRad(-15));
    this.row3.position({ x: -1, y: 5.5, z: 0, gutter: -0.1 });
    this.scene.add(this.row3.mesh);

    this.row4 = new Row(this.world);
    this.row4.build({ size: 12 });
    this.row4.rotateZ(THREE.MathUtils.degToRad(10));
    this.row4.position({ x: 0, y: 0.5, z: 0, gutter: 0.1 });
    this.scene.add(this.row4.mesh);

    this.row5 = new Row(this.world);
    this.row5.build({ size: 12 });
    this.row5.rotateZ(THREE.MathUtils.degToRad(-15));
    this.row5.position({ x: -1, y: -4, z: 0, gutter: -0.1 });
    this.scene.add(this.row5.mesh);
  }

  addEdges() {
    this.edge1 = new Edge();
    this.edge1.build(this.world, "#fbff0e");
    this.edge1.rotate({ x: 0, y: 0, z: THREE.MathUtils.degToRad(90) });
    this.edge1.position({ x: 2, y: 14, z: 0 });
    this.edge1.bottom.body.position = new CANNON.Vec3(
    6.4,
    14.5,
    this.edge1.bottom.position.z);

    this.edge1.bottomInside.position = new CANNON.Vec3(
    6,
    14.2,
    this.edge1.bottom.position.z);

    this.edge1.bottomInside.quaternion.setFromAxisAngle(
    new CANNON.Vec3(0, 0, -1),
    THREE.MathUtils.degToRad(-40));

    this.scene.add(this.edge1.mesh);
    this.edge1.cylinder.rotateX(THREE.MathUtils.degToRad(90));
    this.edge1.cylinder.position.set(2, -1, 0.75);
    this.edge1.mesh.add(this.edge1.cylinder);
    const cylinder2 = this.edge1.cylinder.clone();
    cylinder2.position.set(2, 1.8, 0.75);
    this.edge1.mesh.add(cylinder2);

    this.edge2 = new Edge();
    this.edge2.build(this.world, "#ff0e0e");
    this.edge2.rotate({ x: 0, y: 0, z: THREE.MathUtils.degToRad(90) });
    this.edge2.position({ x: -9, y: 9.8, z: 0 });
    this.edge2.bottom.position.x = 1.55;
    this.edge2.bottom.body.position = new CANNON.Vec3(
    -7.5,
    10,
    this.edge2.bottom.position.z);

    this.edge2.bottomInside.position = new CANNON.Vec3(
    -7,
    10.5,
    this.edge2.bottom.position.z);

    this.edge2.bottomInside.quaternion.setFromAxisAngle(
    new CANNON.Vec3(0, 0, -1),
    THREE.MathUtils.degToRad(35));

    this.scene.add(this.edge2.mesh);
    const cylinder3 = this.edge1.cylinder.clone();
    cylinder3.material = this.edge1.cylinder.material.clone();
    cylinder3.material.color = new THREE.Color("#ff0e0e");
    cylinder3.position.set(4, -1, 0.75);
    this.edge2.mesh.add(cylinder3);
    const cylinder4 = cylinder3.clone();
    cylinder4.position.set(4, 1.8, 0.75);
    this.edge2.mesh.add(cylinder4);

    this.edge3 = new Edge();
    this.edge3.build(this.world, "#15ff47");
    this.edge3.rotate({ x: 0, y: 0, z: THREE.MathUtils.degToRad(90) });
    this.edge3.position({ x: 2, y: 4.8, z: 0 });
    this.edge3.bottom.position.x = 4.45;
    this.edge3.bottom.body.position = new CANNON.Vec3(
    6.5,
    5.5,
    this.edge3.bottom.position.z);

    this.edge3.bottomInside.position = new CANNON.Vec3(
    6,
    5.2,
    this.edge3.bottom.position.z);

    this.edge3.bottomInside.quaternion.setFromAxisAngle(
    new CANNON.Vec3(0, 0, -1),
    THREE.MathUtils.degToRad(-40));

    this.scene.add(this.edge3.mesh);
    const cylinder5 = this.edge1.cylinder.clone();
    cylinder5.material = this.edge1.cylinder.material.clone();
    cylinder5.material.color = new THREE.Color("#15ff47");
    cylinder5.position.set(2, -1, 0.75);
    this.edge3.mesh.add(cylinder5);
    const cylinder6 = cylinder5.clone();
    cylinder6.position.set(2, 1.8, 0.75);
    this.edge3.mesh.add(cylinder6);

    this.edge4 = new Edge();
    this.edge4.build(this.world, "#1c57ff");
    this.edge4.rotate({ x: 0, y: 0, z: THREE.MathUtils.degToRad(90) });
    this.edge4.position({ x: -9, y: 0.3, z: 0 });
    this.edge4.bottom.position.x = 1.55;
    this.edge4.bottom.body.position = new CANNON.Vec3(
    -7.4,
    0.8,
    this.edge4.bottom.position.z);

    this.edge4.bottomInside.position = new CANNON.Vec3(
    -7,
    1,
    this.edge4.bottom.position.z);

    this.edge4.bottomInside.quaternion.setFromAxisAngle(
    new CANNON.Vec3(0, 0, -1),
    THREE.MathUtils.degToRad(40));

    this.scene.add(this.edge4.mesh);
    const cylinder7 = this.edge1.cylinder.clone();
    cylinder7.material = this.edge1.cylinder.material.clone();
    cylinder7.material.color = new THREE.Color("#1c57ff");
    cylinder7.position.set(4, -0.7, 0.75);
    this.edge4.mesh.add(cylinder7);
    const cylinder8 = cylinder7.clone();
    cylinder8.position.set(4, 1.8, 0.75);
    this.edge4.mesh.add(cylinder8);
  }

  addFloorBox() {
    this.floorBox = new FloorBox();
    this.floorBox.build(this.world);
    this.scene.add(this.floorBox.mesh);
  }

  addBackWall() {
    const materialParams = { color: "#1c7dff", side: THREE.DoubleSide };
    const geometry = new THREE.PlaneBufferGeometry(400, 140);
    const material = new THREE.MeshStandardMaterial(materialParams);

    const backwall = new THREE.Mesh(geometry, material);
    backwall.position.z = -10;
    backwall.receiveShadow = true;

    this.scene.add(backwall);
  }

  addSphere() {
    const sphere = new Sphere();
    sphere.build();

    const collideEvent = e => {
      if (
      e.body.material.name === "floor" ||
      e.body.material.name === "sphere")
      {
        sphere.mesh.body.removeEventListener("collide", collideEvent);

        this.moveCameraUp();
      }
    };

    sphere.mesh.body.addEventListener("collide", collideEvent);

    this.world.addBody(sphere.mesh.body);
    const mat = new CANNON.ContactMaterial(
    this.floor.body.material,
    sphere.mesh.body.material,
    { friction: 0.3, restitution: 0.5 });

    this.world.addContactMaterial(mat);

    this.spheres.push(sphere);
    this.scene.add(sphere.mesh);
  }

  addDummyCameraTarget() {
    this.dummyCameraTarget = new THREE.Mesh(
    new THREE.SphereBufferGeometry(0.5, 8, 8),
    new THREE.MeshStandardMaterial());

    this.dummyCameraTarget.material.needsUpdate = true;
    this.dummyCameraTarget.material.opacity = 0;
    this.dummyCameraTarget.material.alphaTest = 1;
    this.dummyCameraTarget.position.y = 20;
    this.dummyCameraTarget.position.z = 2;
    this.scene.add(this.dummyCameraTarget);
  }

  animateDummyCameraTarget() {
    const tl = gsap.timeline({
      defaults: { duration: 11, ease: "sine.out", delay: 0.5 },
      onComplete: () => {
        tl.kill();
      } });


    tl.to(this.dummyCameraTarget.position, { y: -4 });
  }

  moveCameraUp() {
    const tl = gsap.timeline({
      defaults: { duration: 3, ease: "linear", delay: 0.5 },
      onComplete: () => {
        tl.kill();
        this.dummyCameraTarget.position.y = 14;
        this..........完整代码请登录后点击上方下载按钮下载查看

网友评论0