web實踐學習3
web實踐學習3
20201303張奕博 2023.1.26
創建樹
從預覽動圖和頁面可以看到,浮島上共有兩種樹 ??,綠色的高樹和粉紅色的矮樹,樹的實現也非常簡單,是使用了兩個 BoxBufferGeometry 拼接到一起。類 Tree 和 LeafTree 分別用于生成這兩種樹木,接收參數 (x, y, z) 分別表示樹木在場景中的位置信息。我們可以在 Island 輔導上添加一些樹木,構成浮島上的一片小森林。
export default class Tree {
constructor(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
this.treeMesh = new THREE.Group();
this.generate();
}
generate() {
// 樹干
var trunkMat = new THREE.MeshLambertMaterial({
color: 0x543b14,
side: THREE.DoubleSide
});
var trunkGeom = new THREE.BoxBufferGeometry(20, 200, 20);
this.trunkMesh = new THREE.Mesh(trunkGeom, trunkMat);
// 樹葉
var leavesMat = new THREE.MeshLambertMaterial({
color: 0x016316,
side: THREE.DoubleSide
});
var leavesGeom = new THREE.BoxBufferGeometry(80, 400, 80);
this.leavesMesh = new THREE.Mesh(leavesGeom, leavesMat);
this.treeMesh.add(this.trunkMesh);
this.treeMesh.add(this.leavesMesh);
this.treeMesh.position.set(this.x, this.y, this.z);
// ...
}
}
矮樹
export default class LeafTree {
constructor(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
this.treeMesh = new THREE.Group();
this.generate();
}
generate() {
// ...
}
}
創建胡蘿卜
接著,在地面上添加一些胡蘿卜 ??。胡蘿卜身體部分是通過四棱柱 CylinderBufferGeometry 實現的,然后通過 BoxBufferGeometry 立方體來實現胡蘿卜的兩片葉子。場景中可以通過 Carrot 類來添加胡蘿卜,本頁面示例中是通過循環調用添加了 20 個隨機位置的胡蘿卜。
export default class Carrot {
constructor() {
this.carrotMesh = new THREE.Group();
this.generate();
}
generate() {
const carrotMat = new THREE.MeshLambertMaterial({
color: 0xd9721e
});
const leafMat = new THREE.MeshLambertMaterial({
color: 0x339e33
});
// 身體
const bodyGeom = new THREE.CylinderBufferGeometry(5, 3, 12, 4, 1);
this.body = new THREE.Mesh(bodyGeom, carrotMat);
// 葉子
const leafGeom = new THREE.BoxBufferGeometry(5, 10, 1, 1);
this.leaf1 = new THREE.Mesh(leafGeom, leafMat);
this.leaf2 = this.leaf1.clone();
// ...
this.carrotMesh.add(this.body);
this.carrotMesh.add(this.leaf1);
this.carrotMesh.add(this.leaf2);
}
};
for (let i = 0; i < 20; i++) {
carrot[i] = new Carrot();
scene.add(carrot[i].carrotMesh);
carrot[i].carrotMesh.position.set(-170 * Math.random() * 3 - 300, -12, 1400 * Math.random() * 1.2 - 900);
}
創建兔子
最后,來創建頁面的主角兔子 ??。兔子全部都是由立方體 BoxBufferGeometry 搭建而成的,整體可以分解為頭、眼睛、耳朵、鼻子、嘴、胡須、身體、尾巴、四肢等構成,構建兔子時的核心要素就是各個立方體位置和縮放比例的調整,需要具備一定的審美能力,當然本例中使用的兔子是在 Three.js 社區開源代碼的基礎上改造的 ??。
完成兔子的整體外形之后,我們通過 gsap 給兔子添加一些運動動畫效果和方法以供外部調用,其中 blink() 方法用于眨眼、jump() 方法用于原地跳躍、nod() 方法用于點頭、run() 方法用于奔跑、fall() 方法用于邊界檢測時檢測到超出運動范圍時使兔子墜落效果等。完成 Rabbit 類后,我們就可以在場景中初始化小兔子。
import { TweenMax, Power0, Power1, Power4, Elastic, Back } from 'gsap';
export default class Rabbit {
constructor() {
this.bodyInitPositions = [];
this.runningCycle = 0;
this.rabbitMesh = new THREE.Group();
this.bodyMesh = new THREE.Group();
this.headMesh = new THREE.Group();
this.generate();
}
generate() {
var bodyMat = new THREE.MeshLambertMaterial({
color: 0x5c6363
});
var tailMat = new THREE.MeshLambertMaterial({
color: 0xc2bebe
});
var nouseMat = new THREE.MeshLambertMaterial({
color: 0xed716d
});
// ...
var pawMat = new THREE.MeshLambertMaterial({
color: 0xbf6970
});
var bodyGeom = new THREE.BoxBufferGeometry(50, 50, 42, 1);
var headGeom = new THREE.BoxBufferGeometry(44, 44, 54, 1);
var earGeom = new THREE.BoxBufferGeometry(5, 60, 10, 1);
var eyeGeom = new THREE.BoxBufferGeometry(20, 20, 8, 1);
var irisGeom = new THREE.BoxBufferGeometry(8, 8, 8, 1);
var mouthGeom = new THREE.BoxBufferGeometry(8, 16, 4, 1);
var mustacheGeom = new THREE.BoxBufferGeometry(0.5, 1, 22, 1);
var spotGeom = new THREE.BoxBufferGeometry(1, 1, 1, 1);
var legGeom = new THREE.BoxBufferGeometry(33, 33, 10, 1);
var pawGeom = new THREE.BoxBufferGeometry(45, 10, 10, 1);
var pawFGeom = new THREE.BoxBufferGeometry(20, 20, 20, 1);
var tailGeom = new THREE.BoxBufferGeometry(20, 20, 20, 1);
var nouseGeom = new THREE.BoxBufferGeometry(20, 20, 15, 1);
var tailGeom = new THREE.BoxBufferGeometry(23, 23, 23, 1);
this.body = new THREE.Mesh(bodyGeom, bodyMat);
this.bodyMesh.add(this.body);
this.head = new THREE.Mesh(headGeom, bodyMat);
this.bodyMesh.add(this.legL);
this.headMesh.add(this.earR);
this.rabbitMesh.add(this.bodyMesh);
this.rabbitMesh.add(this.headMesh);
// ...
}
blink() {
var sp = 0.5 + Math.random();
if (Math.random() > 0.2)
TweenMax.to([this.eyeR.scale, this.eyeL.scale], sp / 8, {
y: 0,
ease: Power1.easeInOut,
yoyo: true,
repeat: 3
});
}
// 跳躍
jump() {
var speed = 10;
var totalSpeed = 10 / speed;
var jumpHeight = 150;
TweenMax.to(this.earL.rotation, totalSpeed / 2, {
z: "+=.3",
ease: Back.easeOut,
yoyo: true,
repeat: 1
});
TweenMax.to(this.earR.rotation, totalSpeed / 2, {
z: "-=.3",
ease: Back.easeOut,
yoyo: true,
repeat: 1
});
// ...
}
// 點頭
nod() {}
// 奔跑
run() {}
// 移動
move() {}
// 墜落
fall() {}
// 動作銷毀
killNod() {}
killJump() {}
killMove() {}
}

浙公網安備 33010602011771號