Skip to content

165. 实战:躲避汽车

Published:

学完粒子效果之后,我们来做一个实战:躲避汽车

image.png

在道路上随机生成一些汽车,人在道路中间,按键盘左右键来移动躲避汽车。

汽车和人的碰撞我们用包围盒 Box3 来检测。

碰撞的时候需要喷射献血,这个用粒子效果来做。

汽车的模型从 sketchfab 搜索:

https://sketchfab.com/3d-models/low-poly-cartoon-style-car-03-8c7f36b0a60745f487b300fa74d05990

image.png

https://sketchfab.com/3d-models/low-poly-cartoon-style-car-01-69461da2e3a842c0868f5187c1282674

image.png

人的模型也是:

https://sketchfab.com/3d-models/aaron-avatar-b99aa8c330f040649dbda4c082f6328b

image.png

创建项目:

npx create-vite dodge-cars

image.png

进入项目,安装依赖:

npm install
npm install --save three
npm install --save-dev @types/three

改下 src/main.js

import './style.css';
import * as THREE from 'three';
import {
    OrbitControls
} from 'three/addons/controls/OrbitControls.js';
import mesh from './mesh.js';

const scene = new THREE.Scene();

scene.add(mesh);

const light = new THREE.DirectionalLight(0xffffff);
light.position.set(500, 300, 600);
scene.add(light);

const light2 = new THREE.AmbientLight();
scene.add(light2);

const axesHelper = new THREE.AxesHelper(1000);
scene.add(axesHelper);

const width = window.innerWidth;
const height = window.innerHeight;

const camera = new THREE.PerspectiveCamera(60, width / height, 1, 10000);
camera.position.set(0, 500, 500);
camera.lookAt(0, 0, 0);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height)

function render() {
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}

render();

document.body.append(renderer.domElement);

const controls = new OrbitControls(camera, renderer.domElement);

创建 Scene、Light、Camera、Renderer

改下 style.css

body {
    margin: 0;
}

然后创建 mesh.js

import * as THREE from 'three';

const group = new THREE.Group();

const loader = new THREE.TextureLoader();

async function createRoad() {
    const texture = loader.load('./road.png');
    texture.colorSpace = THREE.SRGBColorSpace;
    texture.wrapT = THREE.RepeatWrapping;
    texture.repeat.y = 15;

    const geometry = new THREE.PlaneGeometry(1000, 10000);
    const material = new THREE.MeshLambertMaterial({
        map: texture,
        aoMap: texture
    });
    const road = new THREE.Mesh(geometry, material);
    group.add(road);

    road.rotateX(-Math.PI / 2);    
}
createRoad();

export default group;

用 PlaneGeometry 画马路,旋转一下。

贴上公路的纹理图片,在竖直方向重复 10 次。

road.png 是这张图片:

image.png

road.png

这张图片是网上搜的,截取一部分,竖直方向重复就行:

image.png

跑起来看下:

npm run dev

image.png

2025-06-03 08.23.26.gif

然后把刚才那三个模型下载下来放到 public 目录下:

下载 glb 格式:

https://sketchfab.com/3d-models/low-poly-cartoon-style-car-03-8c7f36b0a60745f487b300fa74d05990#download

image.png

https://sketchfab.com/3d-models/low-poly-cartoon-style-car-01-69461da2e3a842c0868f5187c1282674#download

image.png

https://sketchfab.com/3d-models/aaron-avatar-b99aa8c330f040649dbda4c082f6328b#download

image.png

image.png

加载下:

image.png

const gltfLoader = new GLTFLoader();

async function createCars() {
    const blueCarGltf = await gltfLoader.loadAsync('./blue-car.glb');
    group.add(blueCarGltf.scene);
    console.log(blueCarGltf);
    blueCarGltf.scene.scale.setScalar(100);
}
createRoad();
createCars();

2025-06-03 08.37.13.gif

同样加载下另外两个模型:

image.png

const gltfLoader = new GLTFLoader();

async function createCars() {
    const blueCarGltf = await gltfLoader.loadAsync('./blue-car.glb');
    group.add(blueCarGltf.scene);
    // console.log(blueCarGltf);
    blueCarGltf.scene.scale.setScalar(150);

    const orangeCarGltf = await gltfLoader.loadAsync('./orange-car.glb');
    group.add(orangeCarGltf.scene);
    // console.log(orangeCarGltf);
    orangeCarGltf.scene.scale.setScalar(130);
    orangeCarGltf.scene.position.x = 200;
}

async function createMan() {
    const manGltf = await gltfLoader.loadAsync('./man.glb');
    group.add(manGltf.scene);
    console.log(manGltf);
    manGltf.scene.scale.setScalar(90);
    manGltf.scene.position.z = 200;
}
createRoad();
createCars();
createMan();

去掉 axesHelper,看下效果:

2025-06-03 08.43.05.gif

没啥问题。

案例代码上传了小册仓库

总结

这节我们开始写躲避汽车的实战。

我们用 PlaneGeometry 创建了公路,然后加载了从 sketchfab 找的车和任务模型。

下节让汽车和人动起来。

评论