Commit 27d4b17d authored by Master Q's avatar Master Q

dom 操作添加

parent 0ea1b78f
...@@ -99,13 +99,16 @@ ...@@ -99,13 +99,16 @@
height: 375px !important; height: 375px !important;
display: block; */ display: block; */
/* transform: rotate(90deg); /* transform: rotate(90deg);
transform-origin: center center; */ transform-origin: calc(100vw / 2) calc(100vw / 2); */
} }
</style> </style>
<script src="//yun.duiba.com.cn/aurora/assets/4723050c150b41f362ecf483e9cf98eb31c4a15b.js"></script> <script src="//yun.duiba.com.cn/aurora/assets/4723050c150b41f362ecf483e9cf98eb31c4a15b.js"></script>
</head> </head>
<body> <body>
<canvas id="stage"></canvas> <div class="ss">
<canvas id="stage"></canvas>
</div>
<div id="test"></div>
<script type="importmap"> <script type="importmap">
{ {
"imports": { "imports": {
...@@ -124,11 +127,9 @@ ...@@ -124,11 +127,9 @@
window['hideLoading'] = function() { window['hideLoading'] = function() {
document.querySelector('.load-container').style.display = 'none' document.querySelector('.load-container').style.display = 'none'
} }
console.log(Ammo)
Ammo().then(() => { const dome = document.getElementById('stage')
const dome = document.getElementById('stage') new StageScene(dome)
new StageScene(dome)
})
}) })
</script> </script>
......
...@@ -62662,6 +62662,118 @@ Stats.Panel = function ( name, fg, bg ) { ...@@ -62662,6 +62662,118 @@ Stats.Panel = function ( name, fg, bg ) {
/* harmony default export */ __webpack_exports__["default"] = (Stats); /* harmony default export */ __webpack_exports__["default"] = (Stats);
/***/ }),
/***/ "./src/CarScene/GameConfig.ts":
/*!************************************!*\
!*** ./src/CarScene/GameConfig.ts ***!
\************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GameConfig = void 0;
const THREE = __importStar(__webpack_require__(/*! three */ "./node_modules/_three@0.144.0@three/build/three.module.js"));
const _v3 = new THREE.Vector3();
exports.GameConfig = {
h: 8,
helperDebuger: false,
collisionDebuger: false,
initVehiclePos: new THREE.Vector3(0, 3, 0),
CameraPosConfig: (function () {
let posList = [
0, 8, -20,
0, 20, -16
];
const posListLen = posList.length / 3;
let i = 0;
return {
change() {
_v3.set(posList[i * 3], posList[i * 3 + 1], posList[i * 3 + 2]);
i = (++i) % posListLen;
return _v3;
}
};
})()
};
/***/ }),
/***/ "./src/CarScene/dom.ts":
/*!*****************************!*\
!*** ./src/CarScene/dom.ts ***!
\*****************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Dom = void 0;
exports.Dom = new Proxy({}, {
get(target, property) {
return function (props = {}, ...children) {
const el = document.createElement(property);
const attrs = props.attrs;
const styles = props.styles;
const events = props.events;
if (attrs) {
for (let prop in attrs) {
el.setAttribute(prop, attrs[prop]);
}
}
if (styles) {
for (let k in styles) {
el.style[k] = styles[k];
}
}
if (events) {
for (let eventName in events) {
const cfg = events[eventName];
el.addEventListener(eventName, cfg.callback, cfg.options);
}
}
for (let child of children) {
if (typeof child === 'string') {
console.log('child');
// @ts-ignore
child = document.createTextNode(child);
}
// @ts-ignore
child && el.appendChild(child);
}
return el;
};
}
});
/***/ }), /***/ }),
/***/ "./src/CarScene/index.ts": /***/ "./src/CarScene/index.ts":
...@@ -62710,6 +62822,10 @@ const GLTFLoader_1 = __webpack_require__(/*! ../module/loaders/GLTFLoader */ "./ ...@@ -62710,6 +62822,10 @@ const GLTFLoader_1 = __webpack_require__(/*! ../module/loaders/GLTFLoader */ "./
const tools_1 = __webpack_require__(/*! ./tools */ "./src/CarScene/tools.ts"); const tools_1 = __webpack_require__(/*! ./tools */ "./src/CarScene/tools.ts");
const stats_module_1 = __importDefault(__webpack_require__(/*! three/examples/jsm/libs/stats.module */ "./node_modules/_three@0.144.0@three/examples/jsm/libs/stats.module.js")); const stats_module_1 = __importDefault(__webpack_require__(/*! three/examples/jsm/libs/stats.module */ "./node_modules/_three@0.144.0@three/examples/jsm/libs/stats.module.js"));
const RES_1 = __webpack_require__(/*! ../module/RES */ "./src/module/RES.ts"); const RES_1 = __webpack_require__(/*! ../module/RES */ "./src/module/RES.ts");
const GameConfig_1 = __webpack_require__(/*! ./GameConfig */ "./src/CarScene/GameConfig.ts");
const dom_1 = __webpack_require__(/*! ./dom */ "./src/CarScene/dom.ts");
const ResJson_1 = __webpack_require__(/*! ../ResJson */ "./src/ResJson.ts");
const __1 = __webpack_require__(/*! .. */ "./src/index.ts");
function gradTexture(color) { function gradTexture(color) {
var c = document.createElement("canvas"); var c = document.createElement("canvas");
var ct = c.getContext("2d"); var ct = c.getContext("2d");
...@@ -62759,14 +62875,57 @@ function basicTexture(n) { ...@@ -62759,14 +62875,57 @@ function basicTexture(n) {
const GeometryMap = { const GeometryMap = {
'box': new THREE.BoxGeometry(1, 1, 1) 'box': new THREE.BoxGeometry(1, 1, 1)
}; };
function setStyle(dom, styles) {
for (let k in styles) {
dom.style[k] = styles[k];
}
}
var ZERO_QUATERNION = new THREE.Quaternion(0, 0, 0, 1); var ZERO_QUATERNION = new THREE.Quaternion(0, 0, 0, 1);
const GLTFLoaderIns = new GLTFLoader_1.GLTFLoader(); const GLTFLoaderIns = new GLTFLoader_1.GLTFLoader();
const _defaultVector3 = new THREE.Vector3(); const _defaultVector3 = new THREE.Vector3();
const _rayCaster = new THREE.Raycaster(); const _rayCaster = new THREE.Raycaster();
const _v3 = new THREE.Vector3(); const _v3 = new THREE.Vector3();
class CarScene extends PerspectiveScene_1.PerspectiveScene { class CarScene extends PerspectiveScene_1.PerspectiveScene {
constructor() { constructor(d) {
super(); super(d);
this.onDeviceOrientationChange = () => {
this.timeoutId && clearTimeout(this.timeoutId);
this.timeoutId = setTimeout(() => {
let isPortrait = false; // 是否是 竖屏
if (window.orientation === 180 || window.orientation === 0) {
isPortrait = true;
// 竖屏
this.camera.aspect = window.innerHeight / window.innerWidth;
// 更新相机的投影矩阵
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerHeight, window.innerWidth);
setStyle(this.rendererDom.parentElement, {
transform: 'rotate(90deg)',
transformOrigin: 'calc(100vw / 2) calc(100vw / 2)'
});
this.UICtn.style.width = '100vh';
}
if (window.orientation === 90 || window.orientation === -90) {
isPortrait = false;
// 横屏
this.camera.aspect = window.innerWidth / window.innerHeight;
// 更新相机的投影矩阵
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
setStyle(this.rendererDom.parentElement, {
transform: 'none',
transformOrigin: 'calc(100vw / 2) calc(100vw / 2)'
});
this.UICtn.style.width = '100vw';
}
__1.GDispather.dispatchEvent('orientationChange', {
isPortrait
});
}, 50);
};
this.preSpeedNum = 0; // 前一帧速度
this.preVehiclePositionY = 0; // 前一帧高度
this._currDistance = 0;
this.camera.position.set(20, 20, 20); this.camera.position.set(20, 20, 20);
this.camera.far = 400; this.camera.far = 400;
this.OrbitControlsIns.enabled = false; this.OrbitControlsIns.enabled = false;
...@@ -62776,12 +62935,19 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -62776,12 +62935,19 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
// document.body.addEventListener('click', () => { // document.body.addEventListener('click', () => {
// this.cameraControls.lock() // this.cameraControls.lock()
// }) // })
this.cameraPos = GameConfig_1.GameConfig.CameraPosConfig.change();
this.initStats(); this.initStats();
this.initEvents(); this.initEvents();
this.initRenderer();
} }
get groupNames() { get groupNames() {
return ['gltf', 'skybox']; return ['gltf', 'skybox'];
} }
// 初始化 render
initRenderer() {
this.init2DUi();
this.onDeviceOrientationChange();
}
initStats() { initStats() {
const statsIns = (0, stats_module_1.default)(); const statsIns = (0, stats_module_1.default)();
console.log('===========Stats: ============\n', statsIns); console.log('===========Stats: ============\n', statsIns);
...@@ -62796,10 +62962,20 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -62796,10 +62962,20 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
}); });
} }
ViewDraw() { ViewDraw() {
const reflectionCube = new THREE.CubeTextureLoader() const reflectionCube = new THREE.CubeTexture();
.setPath('/resource/skybox/') const map = {
.load(['px1.jpg', 'nx1.jpg', 'py1.jpg', 'ny1.jpg', 'pz1.jpg', 'nz1.jpg']); 0: 'px1.jpg',
1: 'nx1.jpg',
2: 'py1.jpg',
3: 'ny1.jpg',
4: 'pz1.jpg',
5: 'nz1.jpg'
};
for (let k in map) {
reflectionCube.image[k] = RES_1.RES.getRes(map[(k)]).image;
}
reflectionCube.encoding = THREE.sRGBEncoding; reflectionCube.encoding = THREE.sRGBEncoding;
reflectionCube.needsUpdate = true;
this.scene.background = reflectionCube; this.scene.background = reflectionCube;
// let pmremGenerator = new THREE.PMREMGenerator(this.renderer) // let pmremGenerator = new THREE.PMREMGenerator(this.renderer)
// pmremGenerator.compileEquirectangularShader(); // pmremGenerator.compileEquirectangularShader();
...@@ -62811,7 +62987,6 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -62811,7 +62987,6 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
dirLight.castShadow = true; dirLight.castShadow = true;
dirLight.position.set(20, 20, 20); dirLight.position.set(20, 20, 20);
this.scene.add(dirLight); this.scene.add(dirLight);
this.scene.add(new THREE.DirectionalLightHelper(dirLight));
this.scene.add(new THREE.AmbientLight(0x222222, 1)); this.scene.add(new THREE.AmbientLight(0x222222, 1));
dirLight.castShadow = true; dirLight.castShadow = true;
console.log(dirLight.shadow); console.log(dirLight.shadow);
...@@ -62824,7 +62999,6 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -62824,7 +62999,6 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
dirLight.shadow.camera.bottom = -20; dirLight.shadow.camera.bottom = -20;
dirLight.shadow.camera.right = -20; dirLight.shadow.camera.right = -20;
dirLight.shadow.radius = 4; dirLight.shadow.radius = 4;
this.scene.add(new THREE.CameraHelper(dirLight.shadow.camera));
let renderer = this.renderer; let renderer = this.renderer;
// 开启阴影 // 开启阴影
renderer.shadowMap.enabled = true; renderer.shadowMap.enabled = true;
...@@ -62834,14 +63008,207 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -62834,14 +63008,207 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
// THREE.VSMShadowMap-性能差,约束多,但能够产生意想不到的效果。 // THREE.VSMShadowMap-性能差,约束多,但能够产生意想不到的效果。
renderer.shadowMap.type = THREE.PCFSoftShadowMap; renderer.shadowMap.type = THREE.PCFSoftShadowMap;
this.scene.add(new THREE.AmbientLight(0x3D4143)); this.scene.add(new THREE.AmbientLight(0x3D4143));
this.scene.add(new THREE.AxesHelper(100)); if (GameConfig_1.GameConfig.helperDebuger) {
this.scene.add(new THREE.GridHelper(100, 20)); this.scene.add(new THREE.DirectionalLightHelper(dirLight));
this.scene.add(new THREE.CameraHelper(dirLight.shadow.camera));
this.scene.add(new THREE.AxesHelper(100));
this.scene.add(new THREE.GridHelper(100, 20));
}
// let imgTexture = new THREE.TextureLoader().load('judgeLineMap.png') // let imgTexture = new THREE.TextureLoader().load('judgeLineMap.png')
// // @ts-ignore // // @ts-ignore
// window['imgTexture'] = imgTexture // window['imgTexture'] = imgTexture
// console.log('=======imgTexture=======', imgTexture, imgTexture.image) // console.log('=======imgTexture=======', imgTexture, imgTexture.image)
this.initAmmoPhySicWorld(); this.initAmmoPhySicWorld();
} }
init2DUi() {
// @ts-ignore
const remScale = window['remScale'] || 0.5;
this.UICtn = dom_1.Dom.div({
attrs: {
class: '2d-ui'
},
styles: {
position: 'fixed',
bottom: '20px',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'flex-end',
width: '100%',
boxSizing: 'border-box',
padding: `0 ${100 * remScale}px`
}
}, GameConfig_1.GameConfig.helperDebuger && dom_1.Dom.div({
attrs: {
class: 'tips'
},
styles: {
position: 'fixed',
right: '0',
bottom: '0',
padding: '3px 10px',
backgroundColor: 'yellow'
}
}, '暂未提交分数'), GameConfig_1.GameConfig.helperDebuger && dom_1.Dom.div({
attrs: {
id: 'speedBoard'
},
styles: {
position: 'fixed',
backgroundColor: 'yellow',
padding: '3px 20px',
left: "0px",
bottom: "0px"
}
}), dom_1.Dom.div({
attrs: {
class: 'camera-icon'
},
styles: {
position: 'absolute',
backgroundImage: `url(${ResJson_1.ResJson.path}UI/camera-icon.png)`,
backgroundSize: '100% 100%',
width: `${67 * remScale}px`,
height: `${67 * remScale}px`,
right: `${100 * remScale}px`,
top: `-${200 * remScale}px`
},
events: {
touchstart: {
callback: () => {
this.cameraPos = GameConfig_1.GameConfig.CameraPosConfig.change();
}
}
}
}), dom_1.Dom.div({
attrs: {
class: 'left-cont',
},
styles: {
display: 'flex',
alignItems: 'flex-end'
}
}, dom_1.Dom.div({
attrs: {
class: 'reset-icon'
},
styles: {
backgroundImage: `url(${ResJson_1.ResJson.path}UI/reset-icon.png)`,
backgroundSize: '100% 100%',
width: `${67 * remScale}px`,
height: `${67 * remScale}px`
},
events: {
click: {
callback: () => {
const pos = GameConfig_1.GameConfig.initVehiclePos;
const transformIns = this.vehicleIns.chassisRidigBody.getWorldTransform();
transformIns.setOrigin(new Ammo.btVector3(pos.x, pos.y, pos.z));
transformIns.setRotation(new Ammo.btQuaternion(ZERO_QUATERNION.x, ZERO_QUATERNION.y, ZERO_QUATERNION.z, ZERO_QUATERNION.w));
}
}
}
}), dom_1.Dom.div({
attrs: {
class: 'left-icon',
},
styles: {
backgroundImage: `url(${ResJson_1.ResJson.path}UI/left-icon.png)`,
backgroundSize: '100% 100%',
width: `${70 * remScale}px`,
height: `${126 * remScale}px`,
marginLeft: '40px'
},
events: {
touchstart: {
callback: () => {
this.vehicleIns.doAction('left');
}
},
touchend: {
callback: () => {
this.vehicleIns.cancelAction('left');
}
}
}
}), dom_1.Dom.div({
attrs: {
class: 'right-icon',
},
styles: {
backgroundImage: `url(${ResJson_1.ResJson.path}UI/right-icon.png)`,
backgroundSize: '100% 100%',
width: `${70 * remScale}px`,
height: `${126 * remScale}px`,
marginLeft: '40px'
},
events: {
touchstart: {
callback: () => {
this.vehicleIns.doAction('right');
}
},
touchend: {
callback: () => {
this.vehicleIns.cancelAction('right');
}
}
}
})), dom_1.Dom.div({
attrs: {
class: 'right-cont'
},
styles: {
display: 'flex',
alignItems: 'flex-end'
}
}, dom_1.Dom.div({
attrs: {
class: 'brake-icon',
},
styles: {
backgroundImage: `url(${ResJson_1.ResJson.path}UI/brake-icon.png)`,
backgroundSize: '100% 100%',
width: `${102 * remScale}px`,
height: `${150 * remScale}px`,
},
events: {
touchstart: {
callback: () => {
this.vehicleIns.doAction('braking');
}
},
touchend: {
callback: () => {
this.vehicleIns.cancelAction('braking');
}
}
}
}), dom_1.Dom.div({
attrs: {
class: 'engine-icon',
},
styles: {
backgroundImage: `url(${ResJson_1.ResJson.path}UI/engine-icon.png)`,
backgroundSize: '100% 100%',
width: `${93 * remScale}px`,
height: `${185 * remScale}px`,
marginLeft: '40px'
},
events: {
touchstart: {
callback: () => {
this.vehicleIns.doAction('acceleration');
}
},
touchend: {
callback: () => {
this.vehicleIns.cancelAction('acceleration');
}
}
}
})));
this.rendererDom.parentNode.appendChild(this.UICtn);
}
addMapWall() { addMapWall() {
const wallList = [ const wallList = [
{ {
...@@ -62907,8 +63274,6 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -62907,8 +63274,6 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
} }
}); });
this.terrainMesh = terrainMesh; this.terrainMesh = terrainMesh;
// @ts-ignore
window['terrainMesh'] = terrainMesh;
if (terrainMesh) { if (terrainMesh) {
terrainMesh.receiveShadow = true; terrainMesh.receiveShadow = true;
// terrainMesh.castShadow = true // terrainMesh.castShadow = true
...@@ -62935,7 +63300,7 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -62935,7 +63300,7 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
mass: 0 mass: 0
})); }));
// 添加车 // 添加车
const vehicleIns = this.vehicleIns = new vehicle_1.Vehicle(new THREE.Vector3(10, 10, 0), ZERO_QUATERNION); const vehicleIns = this.vehicleIns = new vehicle_1.Vehicle(GameConfig_1.GameConfig.initVehiclePos, ZERO_QUATERNION);
this.scene.add(vehicleIns); this.scene.add(vehicleIns);
this.ammoPhysicWorld.addDynamicBody(vehicleIns); this.ammoPhysicWorld.addDynamicBody(vehicleIns);
// @ts-ignore // @ts-ignore
...@@ -62964,75 +63329,60 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -62964,75 +63329,60 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
// mass: 0 // mass: 0
// } // }
// )) // ))
// 下面是测试模型数据 if (GameConfig_1.GameConfig.collisionDebuger) {
const boxGeometry = new THREE.BoxGeometry(1, 1, 1, 10, 10, 10); // 下面是测试模型数据
const material = new THREE.MeshLambertMaterial({ const boxGeometry = new THREE.BoxGeometry(1, 1, 1, 10, 10, 10);
// wireframe: true,
// map: new THREE.TextureLoader().load('http://qnpic.top/yoona2.jpg'),
color: new THREE.Color(0xffffff * Math.random())
});
const boxMesh = new THREE.Mesh(boxGeometry, material);
boxMesh.castShadow = true;
const rigidBody = (0, tools_1.createRigidBodyByThreeObject)(boxMesh, {
pos: new THREE.Vector3(5, 0.5, 5),
mass: 0
});
this.scene.add(boxMesh);
this.ammoPhysicWorld.addRigidBodyWithMeshObj(rigidBody);
console.log('boxMesh: ', boxMesh);
const path = new THREE.CatmullRomCurve3([
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(0, 5, 0),
new THREE.Vector3(5, 10, 5),
new THREE.Vector3(10, 5, 10),
new THREE.Vector3(10, 0, 10)
]);
const tt = new THREE.Mesh(new THREE.TubeGeometry(path, 40, 2, 8, false), new THREE.MeshPhongMaterial({ color: 0x990000, wireframe: true }));
this.scene.add(tt);
tt.position.y = 0;
// @ts-ignore
window.tt = tt;
this.ammoPhysicWorld.addRigidBodyWithMeshObj((0, tools_1.createRigidBodyByThreeObject)(tt, {
mass: 0,
pos: new THREE.Vector3(0, 0, 5)
}));
// const geometry = tt.geometry
// const triangleMesh = new Ammo.btTriangleMesh(true, true)
// const test1 = new THREE.Mesh(
// new THREE.BoxGeometry(10, 10, 2),
// new THREE.MeshBasicMaterial({
// color: 0x000000,
// wireframe: true
// })
// )
// createRigidBodyByThreeObject(test1, {
// pos: new THREE.Vector3(10, 5, 5),
// mass: 0
// })
// this.scene.add(test1)
// // @ts-ignore
// window.test1 = test1
// this.ammoPhysicWorld.addRigidBodyWithMeshObj(test1.geometry.userData.physicsBody)
Array.from({
length: 10
}, (_) => {
const boxGeometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshLambertMaterial({ const material = new THREE.MeshLambertMaterial({
// wireframe: true, // wireframe: true,
// map: new THREE.TextureLoader().load('http://qnpic.top/yoona2.jpg'), // map: new THREE.TextureLoader().load('http://qnpic.top/yoona2.jpg'),
color: 0x000000 color: new THREE.Color(0xffffff * Math.random())
}); });
material.color = new THREE.Color(0xffffff * Math.random());
const boxMesh = new THREE.Mesh(boxGeometry, material); const boxMesh = new THREE.Mesh(boxGeometry, material);
boxMesh.position.set(-Math.random() * 20, 10, -Math.random() * 20);
boxMesh.castShadow = true; boxMesh.castShadow = true;
const rigidBody = (0, tools_1.createRigidBodyByThreeObject)(boxMesh, {
pos: new THREE.Vector3(5, 0.5, 5),
mass: 0
});
this.scene.add(boxMesh); this.scene.add(boxMesh);
this.ammoPhysicWorld.addMesh(boxMesh, { this.ammoPhysicWorld.addRigidBodyWithMeshObj(rigidBody);
mass: 1, console.log('boxMesh: ', boxMesh);
// friction: 10, const path = new THREE.CatmullRomCurve3([
restitution: 1 new THREE.Vector3(0, 0, 0),
new THREE.Vector3(0, 5, 0),
new THREE.Vector3(5, 10, 5),
new THREE.Vector3(10, 5, 10),
new THREE.Vector3(10, 0, 10)
]);
const tt = new THREE.Mesh(new THREE.TubeGeometry(path, 40, 2, 8, false), new THREE.MeshPhongMaterial({ color: 0x990000, wireframe: true }));
this.scene.add(tt);
tt.position.y = 0;
// @ts-ignore
window.tt = tt;
this.ammoPhysicWorld.addRigidBodyWithMeshObj((0, tools_1.createRigidBodyByThreeObject)(tt, {
mass: 0,
pos: new THREE.Vector3(0, 0, 5)
}));
Array.from({
length: 10
}, (_) => {
const boxGeometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshLambertMaterial({
// wireframe: true,
// map: new THREE.TextureLoader().load('http://qnpic.top/yoona2.jpg'),
color: 0x000000
});
material.color = new THREE.Color(0xffffff * Math.random());
const boxMesh = new THREE.Mesh(boxGeometry, material);
boxMesh.position.set(-Math.random() * 20, 10, -Math.random() * 20);
boxMesh.castShadow = true;
this.scene.add(boxMesh);
this.ammoPhysicWorld.addMesh(boxMesh, {
mass: 1,
// friction: 10,
restitution: 1
});
}); });
}); }
// Array.from({ // Array.from({
// length: 10 // length: 10
// }, (_, index) => { // }, (_, index) => {
...@@ -63121,12 +63471,26 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -63121,12 +63471,26 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
}; };
} }
initEvents() { initEvents() {
this.addEventListener(PerspectiveScene_1.EVENTS_ENUM.ENTERFRAME, this.updateOimoPhysics, this);
this.addEventListener(PerspectiveScene_1.EVENTS_ENUM.ENTERFRAME, this.onEnterFrame, this); this.addEventListener(PerspectiveScene_1.EVENTS_ENUM.ENTERFRAME, this.onEnterFrame, this);
window.addEventListener("onorientationchange" in window ? "orientationchange" : "resize", this.onDeviceOrientationChange, false);
}
removeEvents() {
this.removeEventListener(PerspectiveScene_1.EVENTS_ENUM.ENTERFRAME, this.onEnterFrame);
window.removeEventListener("onorientationchange" in window ? "orientationchange" : "resize", this.onDeviceOrientationChange, false);
} }
updateOimoPhysics() { destroy() {
super.destroy();
this.removeEvents();
this.UICtn.remove();
}
get currDistance() {
return this._currDistance;
}
set currDistance(v) {
this._currDistance = v;
} }
onEnterFrame(e) { onEnterFrame(e) {
const delta = e.data.delta;
if (this.physicWorld) { if (this.physicWorld) {
this.physicWorld.step(); this.physicWorld.step();
} }
...@@ -63134,6 +63498,44 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -63134,6 +63498,44 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
this.ammoPhysicWorld.step(); this.ammoPhysicWorld.step();
} }
this.updateCamera(this.camera); this.updateCamera(this.camera);
if (this.vehicleIns && this.UICtn) {
const h = this.vehicleIns.chassisMesh.position.y;
const currSpeedNum = this.vehicleIns.speedNum;
const minH = GameConfig_1.GameConfig.h;
this.UICtn.querySelector('#speedBoard') && (this.UICtn.querySelector('#speedBoard').innerHTML = (currSpeedNum < 0 ? '(R) ' : '') + Math.abs(currSpeedNum).toFixed(1) + ' km/h');
// 高于 一定高度
if (h > minH) {
// this.currDistance += currSpeedNum * delta
if (this.preVehiclePositionY < minH) {
// 刚开始进入
this.currDistance = 0;
this.currDistance += currSpeedNum * delta;
}
else {
const isReversal = currSpeedNum * this.preSpeedNum < 0;
if (isReversal) {
this.onGameSubmit(this.currDistance);
this.currDistance = 0;
}
this.currDistance += currSpeedNum * delta;
}
}
else {
if (this.currDistance != 0) {
// 提交
this.onGameSubmit(this.currDistance);
this.currDistance = 0;
}
}
this.preVehiclePositionY = h;
this.preSpeedNum = currSpeedNum;
}
}
onGameSubmit(n) {
console.log('当前分数:', Math.abs(n));
if (this.UICtn.querySelector('.tips')) {
this.UICtn.querySelector('.tips').textContent = '当前提交分数:' + Math.abs(n).toFixed(2);
}
} }
updateCamera(camera) { updateCamera(camera) {
if (this.vehicleIns && !this.OrbitControlsIns.enabled) { if (this.vehicleIns && !this.OrbitControlsIns.enabled) {
...@@ -63141,14 +63543,14 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene { ...@@ -63141,14 +63543,14 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
// 跟随 Car // 跟随 Car
// 0, 8, -20 // 0, 8, -20
// 0, 20, -16 // 0, 20, -16
_defaultVector3.set(0, 8, -20); _defaultVector3.copy(this.cameraPos);
// @ts-ignore // @ts-ignore
window['vehicle'] || (window['vehicle'] = this.vehicleIns.chassisMesh); window['vehicle'] || (window['vehicle'] = this.vehicleIns.chassisMesh);
// const m3 = new THREE.Matrix3() // const m3 = new THREE.Matrix3()
// relativeCameraOffset.applyMatrix3(m3.setFromMatrix4(this.vehicleIns.chassisMesh.matrixWorld)) // relativeCameraOffset.applyMatrix3(m3.setFromMatrix4(this.vehicleIns.chassisMesh.matrixWorld))
const vehiclePosition = this.vehicleIns.chassisMesh.position; const vehiclePosition = this.vehicleIns.chassisMesh.position;
_defaultVector3.applyMatrix4(this.vehicleIns.chassisMesh.matrixWorld); _defaultVector3.applyMatrix4(this.vehicleIns.chassisMesh.matrixWorld);
_defaultVector3.y = this.vehicleIns.chassisMesh.position.y + 8; _defaultVector3.y = this.vehicleIns.chassisMesh.position.y + this.cameraPos.y;
_v3.subVectors(_defaultVector3, vehiclePosition); _v3.subVectors(_defaultVector3, vehiclePosition);
_rayCaster.near = 0; _rayCaster.near = 0;
_rayCaster.far = _v3.length(); _rayCaster.far = _v3.length();
...@@ -63480,7 +63882,7 @@ class Vehicle extends PreloadGroup_1.PreloadGroup { ...@@ -63480,7 +63882,7 @@ class Vehicle extends PreloadGroup_1.PreloadGroup {
constructor(pos, quat) { constructor(pos, quat) {
super(); super();
this.wheelMeshes = []; this.wheelMeshes = [];
this.createWheelMesh = (radius, width) => { this.createWheelMesh = (radius, width, pos) => {
const group = new THREE.Group(); const group = new THREE.Group();
var t = new THREE.CylinderGeometry(radius, radius, width, 24, 1); var t = new THREE.CylinderGeometry(radius, radius, width, 24, 1);
t.rotateZ(Math.PI / 2); t.rotateZ(Math.PI / 2);
...@@ -63493,6 +63895,7 @@ class Vehicle extends PreloadGroup_1.PreloadGroup { ...@@ -63493,6 +63895,7 @@ class Vehicle extends PreloadGroup_1.PreloadGroup {
luntai.visible = !VehicleDebugConfig.debugger; luntai.visible = !VehicleDebugConfig.debugger;
group.add(luntai); group.add(luntai);
this.add(group); this.add(group);
group.position.set(pos.x(), pos.y(), pos.z());
return group; return group;
}; };
// Raycast Vehicle // Raycast Vehicle
...@@ -63553,113 +63956,6 @@ class Vehicle extends PreloadGroup_1.PreloadGroup { ...@@ -63553,113 +63956,6 @@ class Vehicle extends PreloadGroup_1.PreloadGroup {
// new THREE.BoxGeometry(1, 1, 1), // new THREE.BoxGeometry(1, 1, 1),
// materialDynamic // materialDynamic
// )) // ))
this.sppedBoard = createElement('div', 'speedboard', {
position: 'fixed',
backgroundColor: 'yellow',
padding: '3px 20px',
left: "0px",
bottom: "0px"
});
createElement('div', 'left', {
position: 'fixed',
width: '80px',
height: '80px',
backgroundColor: 'blue',
left: '30px',
bottom: '30px'
}, {
mousedown: () => {
this.doAction('left');
},
mouseup: () => {
this.cancelAction('left');
},
touchstart: (e) => {
const target = e.target;
target.style.backgroundColor = target.touchColor;
this.doAction('left');
},
touchend: (e) => {
const target = e.target;
target.style.backgroundColor = target.originColor;
this.cancelAction('left');
}
});
createElement('div', 'right', {
position: 'fixed',
width: '80px',
height: '80px',
backgroundColor: 'blue',
left: '130px',
bottom: '30px'
}, {
mousedown: () => {
this.doAction('right');
},
mouseup: () => {
this.cancelAction('right');
},
touchstart: (e) => {
const target = e.target;
target.style.backgroundColor = target.touchColor;
this.doAction('right');
},
touchend: (e) => {
const target = e.target;
target.style.backgroundColor = target.originColor;
this.cancelAction('right');
}
});
createElement('div', 'acceleration', {
position: 'fixed',
width: '80px',
height: '80px',
backgroundColor: 'blue',
right: '130px',
bottom: '30px'
}, {
mousedown: () => {
this.doAction('acceleration');
},
mouseup: () => {
this.cancelAction('acceleration');
},
touchstart: (e) => {
const target = e.target;
target.style.backgroundColor = target.touchColor;
this.doAction('acceleration');
},
touchend: (e) => {
const target = e.target;
target.style.backgroundColor = target.originColor;
this.cancelAction('acceleration');
}
});
createElement('div', 'braking', {
position: 'fixed',
width: '80px',
height: '80px',
backgroundColor: 'blue',
right: '30px',
bottom: '30px'
}, {
mousedown: () => {
this.doAction('braking');
},
mouseup: () => {
this.cancelAction('braking');
},
touchstart: (e) => {
const target = e.target;
target.style.backgroundColor = target.touchColor;
this.doAction('braking');
},
touchend: (e) => {
const target = e.target;
target.style.backgroundColor = target.originColor;
this.cancelAction('braking');
}
});
} }
/** /**
* 添加轮子 * 添加轮子
...@@ -63688,7 +63984,7 @@ class Vehicle extends PreloadGroup_1.PreloadGroup { ...@@ -63688,7 +63984,7 @@ class Vehicle extends PreloadGroup_1.PreloadGroup {
wheelInfo.set_m_wheelsDampingCompression(suspensionCompression); wheelInfo.set_m_wheelsDampingCompression(suspensionCompression);
wheelInfo.set_m_frictionSlip(friction); // 摩擦系数 wheelInfo.set_m_frictionSlip(friction); // 摩擦系数
wheelInfo.set_m_rollInfluence(rollInfluence); wheelInfo.set_m_rollInfluence(rollInfluence);
this.wheelMeshes[index] = this.createWheelMesh(radius, width); this.wheelMeshes[index] = this.createWheelMesh(radius, width, pos);
} }
createChassisMesh(w, l, h) { createChassisMesh(w, l, h) {
const group = new THREE.Group(); const group = new THREE.Group();
...@@ -63736,8 +64032,8 @@ class Vehicle extends PreloadGroup_1.PreloadGroup { ...@@ -63736,8 +64032,8 @@ class Vehicle extends PreloadGroup_1.PreloadGroup {
const vehicle = this.raycastVehicle; const vehicle = this.raycastVehicle;
const tuning = this.btVehicleTuning; const tuning = this.btVehicleTuning;
// vehicle.updateFriction(delta) // vehicle.updateFriction(delta)
var speed = vehicle.getCurrentSpeedKmHour(); // 记录当前速度
this.sppedBoard.innerHTML = (speed < 0 ? '(R) ' : '') + Math.abs(speed).toFixed(1) + ' km/h'; const speed = this.speedNum = vehicle.getCurrentSpeedKmHour();
let breakingForce = 0; let breakingForce = 0;
let engineForce = 0; let engineForce = 0;
const isAccelerating = this.actions.acceleration || keyboardState_1.KeyBoardStateStore.isPressed('w'); const isAccelerating = this.actions.acceleration || keyboardState_1.KeyBoardStateStore.isPressed('w');
...@@ -63948,6 +64244,10 @@ Object.defineProperty(exports, "__esModule", { value: true }); ...@@ -63948,6 +64244,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.ResJson = void 0; exports.ResJson = void 0;
exports.ResJson = { exports.ResJson = {
"groups": [ "groups": [
{
"keys": "brake-icon.png,camera-icon.png,engine-icon.png,left-icon.png,reset-icon.png,right-icon.png",
"name": "UI"
},
{ {
"keys": "luntai.gltf,qiche_V6.gltf,shamo_V10.gltf", "keys": "luntai.gltf,qiche_V6.gltf,shamo_V10.gltf",
"name": "gltf" "name": "gltf"
...@@ -63958,7 +64258,7 @@ exports.ResJson = { ...@@ -63958,7 +64258,7 @@ exports.ResJson = {
} }
], ],
// eslint-disable-next-line // eslint-disable-next-line
"path": "https://yun.duiba.com.cn/db_games/activity/template/1663512735/resource/" "path": "https://yun.duiba.com.cn/db_games/activity/template/1663585156/resource/"
}; };
...@@ -64006,24 +64306,33 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge ...@@ -64006,24 +64306,33 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}); });
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.StageScene = void 0; exports.GDispather = exports.StageScene = void 0;
const CarScene_1 = __webpack_require__(/*! ./CarScene */ "./src/CarScene/index.ts"); const CarScene_1 = __webpack_require__(/*! ./CarScene */ "./src/CarScene/index.ts");
const THREE = __importStar(__webpack_require__(/*! three */ "./node_modules/_three@0.144.0@three/build/three.module.js")); const THREE = __importStar(__webpack_require__(/*! three */ "./node_modules/_three@0.144.0@three/build/three.module.js"));
const RES_1 = __webpack_require__(/*! ./module/RES */ "./src/module/RES.ts"); const RES_1 = __webpack_require__(/*! ./module/RES */ "./src/module/RES.ts");
const ResJson_1 = __webpack_require__(/*! ./ResJson */ "./src/ResJson.ts"); const ResJson_1 = __webpack_require__(/*! ./ResJson */ "./src/ResJson.ts");
const EventDispatcher_1 = __webpack_require__(/*! ./module/EventDispatcher */ "./src/module/EventDispatcher.ts");
window['THREE'] = THREE; window['THREE'] = THREE;
class StageScene { class StageScene {
constructor() { constructor(canvas) {
this.renderDom = canvas;
this.initStage(); this.initStage();
} }
initStage() { initStage() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
RES_1.RES.loadConfig(ResJson_1.ResJson); RES_1.RES.loadConfig(ResJson_1.ResJson);
new CarScene_1.CarScene(); // @ts-ignore
Ammo().then(() => {
this.stage = new CarScene_1.CarScene(this.renderDom);
});
}); });
} }
destroy() {
this.stage.destroy();
}
} }
exports.StageScene = StageScene; exports.StageScene = StageScene;
exports.GDispather = new EventDispatcher_1.EventDispatcher();
/***/ }), /***/ }),
...@@ -64261,6 +64570,9 @@ class EventDispatcher { ...@@ -64261,6 +64570,9 @@ class EventDispatcher {
// this.listeners[type]!.splice(index, 1) // this.listeners[type]!.splice(index, 1)
// } // }
} }
removeAllEventListener() {
this.listeners = Object.create(null);
}
onceEventListener(type, listener, context) { onceEventListener(type, listener, context) {
const once = (...args) => { const once = (...args) => {
listener.apply(context, args); listener.apply(context, args);
...@@ -64272,7 +64584,8 @@ class EventDispatcher { ...@@ -64272,7 +64584,8 @@ class EventDispatcher {
if (!this.listeners[type]) { if (!this.listeners[type]) {
return; return;
} }
this.listeners[type].forEach(item => { const array = this.listeners[type].slice(0);
array.forEach(item => {
const { listener, context } = item; const { listener, context } = item;
listener.call(context, { listener.call(context, {
type, type,
...@@ -65123,7 +65436,7 @@ class ScenePreloadGroup extends EventDispatcher_1.EventDispatcher { ...@@ -65123,7 +65436,7 @@ class ScenePreloadGroup extends EventDispatcher_1.EventDispatcher {
ViewDraw() { } ViewDraw() { }
} }
class PerspectiveScene extends ScenePreloadGroup { class PerspectiveScene extends ScenePreloadGroup {
constructor() { constructor(canvasDom) {
super(); super();
/** /**
* window resize * window resize
...@@ -65134,6 +65447,7 @@ class PerspectiveScene extends ScenePreloadGroup { ...@@ -65134,6 +65447,7 @@ class PerspectiveScene extends ScenePreloadGroup {
this.camera.updateProjectionMatrix(); this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight); this.renderer.setSize(window.innerWidth, window.innerHeight);
}; };
this.renderCanvasElement = canvasDom;
this.clock = new three_1.Clock(); this.clock = new three_1.Clock();
this.__initScene(); this.__initScene();
this.__initCamera(); this.__initCamera();
...@@ -65153,7 +65467,7 @@ class PerspectiveScene extends ScenePreloadGroup { ...@@ -65153,7 +65467,7 @@ class PerspectiveScene extends ScenePreloadGroup {
this.scene.add(_camera); this.scene.add(_camera);
} }
__initRenderer() { __initRenderer() {
const matrialSceneCanvas = this.rendererDom = document.createElement('canvas'); const matrialSceneCanvas = this.rendererDom = this.renderCanvasElement || document.createElement('canvas');
matrialSceneCanvas.style.display = 'block'; matrialSceneCanvas.style.display = 'block';
const _renderer = this.renderer = new three_1.WebGLRenderer({ const _renderer = this.renderer = new three_1.WebGLRenderer({
canvas: matrialSceneCanvas, canvas: matrialSceneCanvas,
...@@ -65164,7 +65478,7 @@ class PerspectiveScene extends ScenePreloadGroup { ...@@ -65164,7 +65478,7 @@ class PerspectiveScene extends ScenePreloadGroup {
_renderer.setSize(window.innerWidth, window.innerHeight); _renderer.setSize(window.innerWidth, window.innerHeight);
_renderer.setPixelRatio(window.devicePixelRatio); _renderer.setPixelRatio(window.devicePixelRatio);
_renderer.outputEncoding = three_1.sRGBEncoding; _renderer.outputEncoding = three_1.sRGBEncoding;
document.body.appendChild(_renderer.domElement); // document.body.appendChild(_renderer.domElement)
} }
/** /**
* 初始化事件 * 初始化事件
...@@ -65172,12 +65486,12 @@ class PerspectiveScene extends ScenePreloadGroup { ...@@ -65172,12 +65486,12 @@ class PerspectiveScene extends ScenePreloadGroup {
__initEvents() { __initEvents() {
const OrbitControlsIns = this.OrbitControlsIns = new index_1.OrbitControls(this.camera, this.rendererDom); const OrbitControlsIns = this.OrbitControlsIns = new index_1.OrbitControls(this.camera, this.rendererDom);
this.frameLoop(); this.frameLoop();
window.addEventListener('resize', this.onWindowResize); // window.addEventListener('resize', this.onWindowResize)
} }
/** /**
* 清除事件 * 清除事件
*/ */
removeEvents() { __removeEvents() {
window.removeEventListener('resize', this.onWindowResize); window.removeEventListener('resize', this.onWindowResize);
} }
/** /**
...@@ -65191,7 +65505,12 @@ class PerspectiveScene extends ScenePreloadGroup { ...@@ -65191,7 +65505,12 @@ class PerspectiveScene extends ScenePreloadGroup {
// frame rander // frame rander
this.renderer.render(this.scene, this.camera); this.renderer.render(this.scene, this.camera);
this.OrbitControlsIns.update(); this.OrbitControlsIns.update();
requestAnimationFrame(this.frameLoop.bind(this)); this.requestId = requestAnimationFrame(this.frameLoop.bind(this));
}
destroy() {
cancelAnimationFrame(this.requestId);
this.__removeEvents();
this.removeAllEventListener();
} }
} }
exports.PerspectiveScene = PerspectiveScene; exports.PerspectiveScene = PerspectiveScene;
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
"scripts": { "scripts": {
"dev": "node ./scripts/devServer -p 9016", "dev": "node ./scripts/devServer -p 9016",
"build": "webpack --config webpack.prod.js", "build": "webpack --config webpack.prod.js",
"flushRes": "node scripts/flushRes",
"handleRes": "node scripts/delRel && node scripts/copyRes && node scripts/imageMin", "handleRes": "node scripts/delRel && node scripts/copyRes && node scripts/imageMin",
"upload": "node scripts/upload", "upload": "node scripts/upload",
"prod": "npm run handleRes && npm run upload && npm run buildTS", "prod": "npm run handleRes && npm run upload && npm run buildTS",
......
{ {
"groups": [ "groups": [
{
"keys": "brake-icon.png,camera-icon.png,engine-icon.png,left-icon.png,reset-icon.png,right-icon.png",
"name": "UI"
},
{ {
"keys": "luntai.gltf,qiche_V6.gltf,shamo_V10.gltf", "keys": "luntai.gltf,qiche_V6.gltf,shamo_V10.gltf",
"name": "gltf" "name": "gltf"
......
import * as THREE from 'three'
const _v3 = new THREE.Vector3()
export const GameConfig = {
h: 8,
helperDebuger: false,
collisionDebuger: false,
initVehiclePos: new THREE.Vector3(0, 3, 0),
CameraPosConfig: (function() {
let posList = [
0, 8, -20,
0, 20, -16
]
const posListLen = posList.length / 3
let i = 0
return {
change() {
_v3.set(posList[i * 3], posList[i * 3 + 1], posList[i * 3 + 2])
i = (++i) % posListLen
return _v3
}
}
})()
}
\ No newline at end of file
type CreateElementProps = Partial<{
attrs: Record<string, string>,
styles: Partial<CSSStyleDeclaration>,
events: Partial<Record<keyof WindowEventMap, {
callback: (this: HTMLObjectElement) => any,
options?: boolean | AddEventListenerOptions
}>>
}>
export const Dom = new Proxy(({} as Record<keyof HTMLElementTagNameMap, (p: CreateElementProps, ...children: HTMLObjectElement[] | string[]) => HTMLObjectElement>), {
get(target, property: keyof HTMLElementTagNameMap) {
return function(props:CreateElementProps = {}, ...children: HTMLObjectElement[] | string[]) {
const el = document.createElement(property);
const attrs = props.attrs
const styles = props.styles
const events = props.events
if (
attrs
) {
for (let prop in attrs) {
el.setAttribute(prop, attrs[prop]);
}
}
if (styles) {
for (let k in styles) {
el.style[k] = styles[k]
}
}
if (
events
) {
for (let eventName in events) {
const cfg = events[eventName as keyof WindowEventMap]
el.addEventListener(eventName, cfg.callback, cfg.options)
}
}
for (let child of children) {
if (typeof child === 'string') {
console.log('child')
// @ts-ignore
child = document.createTextNode(child);
}
// @ts-ignore
child && el.appendChild(child);
}
return el;
}
}
});
\ No newline at end of file
...@@ -10,6 +10,10 @@ import { MeshBasicMaterial } from "three"; ...@@ -10,6 +10,10 @@ import { MeshBasicMaterial } from "three";
import Stats from 'three/examples/jsm/libs/stats.module' import Stats from 'three/examples/jsm/libs/stats.module'
import { RoomEnvironment } from '../module/environment/RoomEnvironment'; import { RoomEnvironment } from '../module/environment/RoomEnvironment';
import { RES } from "../module/RES"; import { RES } from "../module/RES";
import { GameConfig } from "./GameConfig";
import { Dom } from "./dom";
import { ResJson } from "../ResJson";
import { GDispather } from "..";
function gradTexture(color: [number[], string[]]) { function gradTexture(color: [number[], string[]]) {
var c = document.createElement("canvas"); var c = document.createElement("canvas");
...@@ -61,6 +65,13 @@ const GeometryMap = { ...@@ -61,6 +65,13 @@ const GeometryMap = {
'box': new THREE.BoxGeometry(1,1,1) 'box': new THREE.BoxGeometry(1,1,1)
} }
function setStyle(dom: HTMLElement, styles: Partial<CSSStyleDeclaration>) {
for (let k in styles) {
dom.style[k] = styles[k]
}
}
var ZERO_QUATERNION = new THREE.Quaternion(0, 0, 0, 1); var ZERO_QUATERNION = new THREE.Quaternion(0, 0, 0, 1);
const GLTFLoaderIns = new GLTFLoader() const GLTFLoaderIns = new GLTFLoader()
...@@ -74,12 +85,13 @@ export class CarScene extends PerspectiveScene { ...@@ -74,12 +85,13 @@ export class CarScene extends PerspectiveScene {
cameraControls: FirstPersonCameraControl cameraControls: FirstPersonCameraControl
dirLight: THREE.DirectionalLight dirLight: THREE.DirectionalLight
terrainMesh: THREE.Mesh terrainMesh: THREE.Mesh
cameraPos: THREE.Vector3
get groupNames(): string[] { get groupNames(): string[] {
return ['gltf', 'skybox'] return ['gltf', 'skybox']
} }
constructor(d: HTMLCanvasElement) { constructor(d: HTMLCanvasElement, u: HTMLElement) {
super(d) super(d)
this.camera.position.set(20, 20, 20) this.camera.position.set(20, 20, 20)
...@@ -92,9 +104,20 @@ export class CarScene extends PerspectiveScene { ...@@ -92,9 +104,20 @@ export class CarScene extends PerspectiveScene {
// document.body.addEventListener('click', () => { // document.body.addEventListener('click', () => {
// this.cameraControls.lock() // this.cameraControls.lock()
// }) // })
this.cameraPos = GameConfig.CameraPosConfig.change()
this.initStats() this.initStats()
this.initEvents() this.initEvents()
this.init2DUi(u)
this.initRenderer()
}
// 初始化 render
initRenderer() {
this.onDeviceOrientationChange()
} }
initStats() { initStats() {
...@@ -113,11 +136,20 @@ export class CarScene extends PerspectiveScene { ...@@ -113,11 +136,20 @@ export class CarScene extends PerspectiveScene {
} }
ViewDraw() { ViewDraw() {
this.camera.rotateZ(Math.PI / 2) const reflectionCube = new THREE.CubeTexture()
const reflectionCube = new THREE.CubeTextureLoader() const map: Record<string, string> = {
.setPath( '/resource/skybox/' ) 0: 'px1.jpg',
.load( [ 'px1.jpg', 'nx1.jpg', 'py1.jpg', 'ny1.jpg', 'pz1.jpg', 'nz1.jpg' ] ); 1: 'nx1.jpg',
2: 'py1.jpg',
3: 'ny1.jpg',
4: 'pz1.jpg',
5: 'nz1.jpg'
}
for (let k in map) {
reflectionCube.image[k] = RES.getRes(map[(k)]).image
}
reflectionCube.encoding = THREE.sRGBEncoding; reflectionCube.encoding = THREE.sRGBEncoding;
reflectionCube.needsUpdate = true
this.scene.background = reflectionCube; this.scene.background = reflectionCube;
// let pmremGenerator = new THREE.PMREMGenerator(this.renderer) // let pmremGenerator = new THREE.PMREMGenerator(this.renderer)
...@@ -132,7 +164,6 @@ export class CarScene extends PerspectiveScene { ...@@ -132,7 +164,6 @@ export class CarScene extends PerspectiveScene {
dirLight.castShadow = true dirLight.castShadow = true
dirLight.position.set(20, 20, 20) dirLight.position.set(20, 20, 20)
this.scene.add(dirLight) this.scene.add(dirLight)
this.scene.add(new THREE.DirectionalLightHelper(dirLight))
this.scene.add(new THREE.AmbientLight(0x222222, 1)) this.scene.add(new THREE.AmbientLight(0x222222, 1))
...@@ -148,8 +179,6 @@ export class CarScene extends PerspectiveScene { ...@@ -148,8 +179,6 @@ export class CarScene extends PerspectiveScene {
dirLight.shadow.camera.right = -20 dirLight.shadow.camera.right = -20
dirLight.shadow.radius = 4 dirLight.shadow.radius = 4
this.scene.add(new THREE.CameraHelper(dirLight.shadow.camera))
let renderer = this.renderer let renderer = this.renderer
// 开启阴影 // 开启阴影
renderer.shadowMap.enabled = true renderer.shadowMap.enabled = true
...@@ -161,8 +190,13 @@ export class CarScene extends PerspectiveScene { ...@@ -161,8 +190,13 @@ export class CarScene extends PerspectiveScene {
this.scene.add(new THREE.AmbientLight(0x3D4143)) this.scene.add(new THREE.AmbientLight(0x3D4143))
this.scene.add(new THREE.AxesHelper(100)) if (GameConfig.helperDebuger) {
this.scene.add(new THREE.GridHelper(100, 20)) this.scene.add(new THREE.DirectionalLightHelper(dirLight))
this.scene.add(new THREE.CameraHelper(dirLight.shadow.camera))
this.scene.add(new THREE.AxesHelper(100))
this.scene.add(new THREE.GridHelper(100, 20))
}
// let imgTexture = new THREE.TextureLoader().load('judgeLineMap.png') // let imgTexture = new THREE.TextureLoader().load('judgeLineMap.png')
// // @ts-ignore // // @ts-ignore
...@@ -173,6 +207,234 @@ export class CarScene extends PerspectiveScene { ...@@ -173,6 +207,234 @@ export class CarScene extends PerspectiveScene {
this.initAmmoPhySicWorld() this.initAmmoPhySicWorld()
} }
UICtn: HTMLElement
init2DUi(d: HTMLElement) {
// @ts-ignore
const remScale = 0.5 // window['remScale'] 这里就写死吧
this.UICtn = Dom.div(
{
attrs: {
class: '2d-ui'
},
styles: {
position: 'fixed',
bottom: '20px',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'flex-end',
width: '100%',
boxSizing: 'border-box',
padding: `0 ${100 * remScale}px`
}
},
GameConfig.helperDebuger && Dom.div(
{
attrs: {
class: 'tips'
},
styles: {
position: 'fixed',
right: '0',
bottom: '0',
padding: '3px 10px',
backgroundColor: 'yellow'
}
},
'暂未提交分数'
)
,
GameConfig.helperDebuger && Dom.div(
{
attrs: {
id: 'speedBoard'
},
styles: {
position: 'fixed',
backgroundColor: 'yellow',
padding: '3px 20px',
left: "0px",
bottom: "0px"
}
}
),
Dom.div(
{
attrs: {
class: 'camera-icon'
},
styles: {
position: 'absolute',
backgroundImage: `url(${ResJson.path}UI/camera-icon.png)`,
backgroundSize: '100% 100%',
width: `${67 * remScale}px`,
height: `${67 * remScale}px`,
right: `${100 * remScale}px`,
top: `-${200 * remScale}px`
},
events: {
touchstart: {
callback: () => {
this.cameraPos = GameConfig.CameraPosConfig.change()
}
}
}
}
),
Dom.div(
{
attrs: {
class: 'left-cont',
},
styles: {
display: 'flex',
alignItems: 'flex-end'
}
},
Dom.div({
attrs: {
class: 'reset-icon'
},
styles: {
backgroundImage: `url(${ResJson.path}UI/reset-icon.png)`,
backgroundSize: '100% 100%',
width: `${67 * remScale}px`,
height: `${67 * remScale}px`
},
events: {
click: {
callback: () => {
const pos = GameConfig.initVehiclePos
const transformIns = this.vehicleIns.chassisRidigBody.getWorldTransform()
transformIns.setOrigin(new Ammo.btVector3(pos.x, pos.y, pos.z))
transformIns.setRotation(
new Ammo.btQuaternion(ZERO_QUATERNION.x, ZERO_QUATERNION.y, ZERO_QUATERNION.z, ZERO_QUATERNION.w)
)
}
}
}
}),
Dom.div({
attrs: {
class: 'left-icon',
},
styles: {
backgroundImage: `url(${ResJson.path}UI/left-icon.png)`,
backgroundSize: '100% 100%',
width: `${70 * remScale}px`,
height: `${126 * remScale}px`,
marginLeft: '40px'
},
events: {
touchstart: {
callback: () => {
this.vehicleIns.doAction('left')
}
},
touchend: {
callback: () => {
this.vehicleIns.cancelAction('left')
}
}
}
}),
Dom.div({
attrs: {
class: 'right-icon',
},
styles: {
backgroundImage: `url(${ResJson.path}UI/right-icon.png)`,
backgroundSize: '100% 100%',
width: `${70 * remScale}px`,
height: `${126 * remScale}px`,
marginLeft: '40px'
},
events: {
touchstart: {
callback: () => {
this.vehicleIns.doAction('right')
}
},
touchend: {
callback: () => {
this.vehicleIns.cancelAction('right')
}
}
}
})
),
Dom.div(
{
attrs: {
class: 'right-cont'
},
styles: {
display: 'flex',
alignItems: 'flex-end'
}
},
Dom.div({
attrs: {
class: 'brake-icon',
},
styles: {
backgroundImage: `url(${ResJson.path}UI/brake-icon.png)`,
backgroundSize: '100% 100%',
width: `${102 * remScale}px`,
height: `${150 * remScale}px`,
},
events: {
touchstart: {
callback: () => {
this.vehicleIns.doAction('braking')
}
},
touchend: {
callback: () => {
this.vehicleIns.cancelAction('braking')
}
}
}
}),
Dom.div({
attrs: {
class: 'engine-icon',
},
styles: {
backgroundImage: `url(${ResJson.path}UI/engine-icon.png)`,
backgroundSize: '100% 100%',
width: `${93 * remScale}px`,
height: `${185 * remScale}px`,
marginLeft: '40px'
},
events: {
touchstart: {
callback: () => {
this.vehicleIns.doAction('acceleration')
}
},
touchend: {
callback: () => {
this.vehicleIns.cancelAction('acceleration')
}
}
}
})
)
)
const uiNode = d || this.rendererDom.parentNode
uiNode.appendChild(this.UICtn)
}
addMapWall() { addMapWall() {
const wallList: { const wallList: {
rotationDeg: number, rotationDeg: number,
...@@ -261,8 +523,6 @@ export class CarScene extends PerspectiveScene { ...@@ -261,8 +523,6 @@ export class CarScene extends PerspectiveScene {
} }
}) })
this.terrainMesh = terrainMesh this.terrainMesh = terrainMesh
// @ts-ignore
window['terrainMesh'] = terrainMesh
if (terrainMesh) { if (terrainMesh) {
terrainMesh.receiveShadow = true terrainMesh.receiveShadow = true
// terrainMesh.castShadow = true // terrainMesh.castShadow = true
...@@ -296,7 +556,7 @@ export class CarScene extends PerspectiveScene { ...@@ -296,7 +556,7 @@ export class CarScene extends PerspectiveScene {
)) ))
// 添加车 // 添加车
const vehicleIns = this.vehicleIns = new Vehicle(new THREE.Vector3(10, 10, 0), ZERO_QUATERNION) const vehicleIns = this.vehicleIns = new Vehicle(GameConfig.initVehiclePos, ZERO_QUATERNION)
this.scene.add(vehicleIns) this.scene.add(vehicleIns)
this.ammoPhysicWorld.addDynamicBody(vehicleIns) this.ammoPhysicWorld.addDynamicBody(vehicleIns)
// @ts-ignore // @ts-ignore
...@@ -315,6 +575,8 @@ export class CarScene extends PerspectiveScene { ...@@ -315,6 +575,8 @@ export class CarScene extends PerspectiveScene {
// @ts-ignore // @ts-ignore
planeMesh.material = terrainMesh.material planeMesh.material = terrainMesh.material
this.scene.add(planeMesh) this.scene.add(planeMesh)
// this.ammoPhysicWorld.addMesh(planeMesh, { // this.ammoPhysicWorld.addMesh(planeMesh, {
// friction: 10, // friction: 10,
// restitution: 0.1, // restitution: 0.1,
...@@ -327,90 +589,71 @@ export class CarScene extends PerspectiveScene { ...@@ -327,90 +589,71 @@ export class CarScene extends PerspectiveScene {
// } // }
// )) // ))
// 下面是测试模型数据 if (GameConfig.collisionDebuger) {
const boxGeometry = new THREE.BoxGeometry(1,1,1, 10, 10, 10) // 下面是测试模型数据
const material = new THREE.MeshLambertMaterial({ const boxGeometry = new THREE.BoxGeometry(1,1,1, 10, 10, 10)
// wireframe: true,
// map: new THREE.TextureLoader().load('http://qnpic.top/yoona2.jpg'),
color: new THREE.Color(0xffffff * Math.random())
})
const boxMesh = new THREE.Mesh(boxGeometry, material)
boxMesh.castShadow = true
const rigidBody = createRigidBodyByThreeObject(boxMesh, {
pos: new THREE.Vector3(5, 0.5, 5),
mass: 0
})
this.scene.add(boxMesh)
this.ammoPhysicWorld.addRigidBodyWithMeshObj(rigidBody)
console.log('boxMesh: ', boxMesh)
const path = new THREE.CatmullRomCurve3([
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(0, 5, 0),
new THREE.Vector3(5, 10, 5),
new THREE.Vector3(10, 5, 10),
new THREE.Vector3(10, 0, 10)
])
const tt = new THREE.Mesh(
new THREE.TubeGeometry(path, 40, 2, 8, false),
new THREE.MeshPhongMaterial( { color:0x990000, wireframe: true } )
)
this.scene.add(tt)
tt.position.y = 0
// @ts-ignore
window.tt = tt
this.ammoPhysicWorld.addRigidBodyWithMeshObj(createRigidBodyByThreeObject(
tt,
{
mass: 0,
pos: new THREE.Vector3(0, 0, 5)
}
))
// const geometry = tt.geometry
// const triangleMesh = new Ammo.btTriangleMesh(true, true)
// const test1 = new THREE.Mesh(
// new THREE.BoxGeometry(10, 10, 2),
// new THREE.MeshBasicMaterial({
// color: 0x000000,
// wireframe: true
// })
// )
// createRigidBodyByThreeObject(test1, {
// pos: new THREE.Vector3(10, 5, 5),
// mass: 0
// })
// this.scene.add(test1)
// // @ts-ignore
// window.test1 = test1
// this.ammoPhysicWorld.addRigidBodyWithMeshObj(test1.geometry.userData.physicsBody)
Array.from({
length: 10
}, (_) => {
const boxGeometry = new THREE.BoxGeometry(1,1,1)
const material = new THREE.MeshLambertMaterial({ const material = new THREE.MeshLambertMaterial({
// wireframe: true, // wireframe: true,
// map: new THREE.TextureLoader().load('http://qnpic.top/yoona2.jpg'), // map: new THREE.TextureLoader().load('http://qnpic.top/yoona2.jpg'),
color: 0x000000 color: new THREE.Color(0xffffff * Math.random())
}) })
material.color = new THREE.Color(0xffffff * Math.random())
const boxMesh = new THREE.Mesh(boxGeometry, material) const boxMesh = new THREE.Mesh(boxGeometry, material)
boxMesh.position.set(-Math.random() * 20, 10, -Math.random() * 20)
boxMesh.castShadow = true boxMesh.castShadow = true
const rigidBody = createRigidBodyByThreeObject(boxMesh, {
pos: new THREE.Vector3(5, 0.5, 5),
mass: 0
})
this.scene.add(boxMesh) this.scene.add(boxMesh)
this.ammoPhysicWorld.addRigidBodyWithMeshObj(rigidBody)
console.log('boxMesh: ', boxMesh)
this.ammoPhysicWorld.addMesh(boxMesh, {
mass: 1, const path = new THREE.CatmullRomCurve3([
// friction: 10, new THREE.Vector3(0, 0, 0),
restitution: 1 new THREE.Vector3(0, 5, 0),
new THREE.Vector3(5, 10, 5),
new THREE.Vector3(10, 5, 10),
new THREE.Vector3(10, 0, 10)
])
const tt = new THREE.Mesh(
new THREE.TubeGeometry(path, 40, 2, 8, false),
new THREE.MeshPhongMaterial( { color:0x990000, wireframe: true } )
)
this.scene.add(tt)
tt.position.y = 0
// @ts-ignore
window.tt = tt
this.ammoPhysicWorld.addRigidBodyWithMeshObj(createRigidBodyByThreeObject(
tt,
{
mass: 0,
pos: new THREE.Vector3(0, 0, 5)
}
))
Array.from({
length: 10
}, (_) => {
const boxGeometry = new THREE.BoxGeometry(1,1,1)
const material = new THREE.MeshLambertMaterial({
// wireframe: true,
// map: new THREE.TextureLoader().load('http://qnpic.top/yoona2.jpg'),
color: 0x000000
})
material.color = new THREE.Color(0xffffff * Math.random())
const boxMesh = new THREE.Mesh(boxGeometry, material)
boxMesh.position.set(-Math.random() * 20, 10, -Math.random() * 20)
boxMesh.castShadow = true
this.scene.add(boxMesh)
this.ammoPhysicWorld.addMesh(boxMesh, {
mass: 1,
// friction: 10,
restitution: 1
})
}) })
}) }
// Array.from({ // Array.from({
// length: 10 // length: 10
...@@ -509,15 +752,78 @@ export class CarScene extends PerspectiveScene { ...@@ -509,15 +752,78 @@ export class CarScene extends PerspectiveScene {
} }
initEvents() { initEvents() {
this.addEventListener(EVENTS_ENUM.ENTERFRAME, this.updateOimoPhysics, this)
this.addEventListener(EVENTS_ENUM.ENTERFRAME, this.onEnterFrame, this) this.addEventListener(EVENTS_ENUM.ENTERFRAME, this.onEnterFrame, this)
window.addEventListener("onorientationchange" in window ? "orientationchange" : "resize", this.onDeviceOrientationChange, false);
} }
updateOimoPhysics() { removeEvents() {
this.removeEventListener(EVENTS_ENUM.ENTERFRAME, this.onEnterFrame)
window.removeEventListener("onorientationchange" in window ? "orientationchange" : "resize", this.onDeviceOrientationChange, false)
}
destroy() {
super.destroy()
this.removeEvents()
this.UICtn.remove()
}
timeoutId: any
onDeviceOrientationChange = () => {
this.timeoutId && clearTimeout(this.timeoutId)
this.timeoutId = setTimeout(() => {
let isPortrait = false // 是否是 竖屏
if (window.orientation === 180 || window.orientation === 0) {
isPortrait = true
// 竖屏
this.camera.aspect = window.innerHeight / window.innerWidth
// 更新相机的投影矩阵
this.camera.updateProjectionMatrix()
this.renderer.setSize(window.innerHeight, window.innerWidth)
setStyle(this.rendererDom.parentElement, {
transform: 'rotate(90deg)',
transformOrigin: 'calc(100vw / 2) calc(100vw / 2)'
})
this.UICtn.style.width = '100vh'
}
if (window.orientation === 90 || window.orientation === -90 ){
isPortrait = false
// 横屏
this.camera.aspect = window.innerWidth / window.innerHeight
// 更新相机的投影矩阵
this.camera.updateProjectionMatrix()
this.renderer.setSize(window.innerWidth, window.innerHeight)
setStyle(this.rendererDom.parentElement, {
transform: 'none',
transformOrigin: 'calc(100vw / 2) calc(100vw / 2)'
})
this.UICtn.style.width = '100vw'
}
GDispather.dispatchEvent('orientationChange', {
isPortrait
})
}, 50)
}
preSpeedNum: number = 0 // 前一帧速度
preVehiclePositionY: number = 0 // 前一帧高度
_currDistance: number = 0
get currDistance() {
return this._currDistance
}
set currDistance(v: number) {
this._currDistance = v
} }
onEnterFrame(e: any) { onEnterFrame(e: any) {
const delta = e.data.delta
if (this.physicWorld) { if (this.physicWorld) {
this.physicWorld.step() this.physicWorld.step()
} }
...@@ -527,6 +833,49 @@ export class CarScene extends PerspectiveScene { ...@@ -527,6 +833,49 @@ export class CarScene extends PerspectiveScene {
} }
this.updateCamera(this.camera) this.updateCamera(this.camera)
if (this.vehicleIns && this.UICtn) {
const h = this.vehicleIns.chassisMesh.position.y
const currSpeedNum = this.vehicleIns.speedNum
const minH = GameConfig.h
this.UICtn.querySelector('#speedBoard') && (this.UICtn.querySelector('#speedBoard').innerHTML = (currSpeedNum < 0 ? '(R) ' : '') + Math.abs(currSpeedNum).toFixed(1) + ' km/h');
// 高于 一定高度
if (h > minH) {
// this.currDistance += currSpeedNum * delta
if (this.preVehiclePositionY < minH) {
// 刚开始进入
this.currDistance = 0
this.currDistance += currSpeedNum * delta
} else {
const isReversal = currSpeedNum * this.preSpeedNum < 0
if (isReversal) {
this.onGameSubmit(this.currDistance)
this.currDistance = 0
}
this.currDistance += currSpeedNum * delta
}
} else {
if (this.currDistance != 0) {
// 提交
this.onGameSubmit(this.currDistance)
this.currDistance = 0
}
}
this.preVehiclePositionY = h
this.preSpeedNum = currSpeedNum
}
}
onGameSubmit(n: number) {
console.log('当前分数:', Math.abs(n))
if (this.UICtn.querySelector('.tips')) {
this.UICtn.querySelector('.tips').textContent = '当前提交分数:' + Math.abs(n).toFixed(2)
}
} }
updateCamera(camera: THREE.Camera) { updateCamera(camera: THREE.Camera) {
...@@ -535,14 +884,14 @@ export class CarScene extends PerspectiveScene { ...@@ -535,14 +884,14 @@ export class CarScene extends PerspectiveScene {
// 跟随 Car // 跟随 Car
// 0, 8, -20 // 0, 8, -20
// 0, 20, -16 // 0, 20, -16
_defaultVector3.set(0, 8, -20) _defaultVector3.copy(this.cameraPos)
// @ts-ignore // @ts-ignore
window['vehicle'] || (window['vehicle'] = this.vehicleIns.chassisMesh) window['vehicle'] || (window['vehicle'] = this.vehicleIns.chassisMesh)
// const m3 = new THREE.Matrix3() // const m3 = new THREE.Matrix3()
// relativeCameraOffset.applyMatrix3(m3.setFromMatrix4(this.vehicleIns.chassisMesh.matrixWorld)) // relativeCameraOffset.applyMatrix3(m3.setFromMatrix4(this.vehicleIns.chassisMesh.matrixWorld))
const vehiclePosition = this.vehicleIns.chassisMesh.position const vehiclePosition = this.vehicleIns.chassisMesh.position
_defaultVector3.applyMatrix4(this.vehicleIns.chassisMesh.matrixWorld) _defaultVector3.applyMatrix4(this.vehicleIns.chassisMesh.matrixWorld)
_defaultVector3.y = this.vehicleIns.chassisMesh.position.y + 8 _defaultVector3.y = this.vehicleIns.chassisMesh.position.y + this.cameraPos.y
_v3.subVectors(_defaultVector3, vehiclePosition) _v3.subVectors(_defaultVector3, vehiclePosition)
_rayCaster.near = 0 _rayCaster.near = 0
_rayCaster.far = _v3.length() _rayCaster.far = _v3.length()
......
...@@ -64,10 +64,11 @@ export class Vehicle extends PreloadGroup{ ...@@ -64,10 +64,11 @@ export class Vehicle extends PreloadGroup{
chassisRidigBody: Ammo.btRigidBody chassisRidigBody: Ammo.btRigidBody
raycastVehicle: Ammo.btRaycastVehicle raycastVehicle: Ammo.btRaycastVehicle
btVehicleTuning: Ammo.btVehicleTuning btVehicleTuning: Ammo.btVehicleTuning
sppedBoard: HTMLElement // 速度面板
luntaiIns: GltfModel // 轮胎模型 luntaiIns: GltfModel // 轮胎模型
speedNum: number
constructor(pos: THREE.Vector3, quat: THREE.Quaternion) { constructor(pos: THREE.Vector3, quat: THREE.Quaternion) {
super() super()
...@@ -122,142 +123,6 @@ export class Vehicle extends PreloadGroup{ ...@@ -122,142 +123,6 @@ export class Vehicle extends PreloadGroup{
// new THREE.BoxGeometry(1, 1, 1), // new THREE.BoxGeometry(1, 1, 1),
// materialDynamic // materialDynamic
// )) // ))
this.sppedBoard = createElement('div', 'speedboard', {
position: 'fixed',
backgroundColor: 'yellow',
padding: '3px 20px',
left: "0px",
bottom: "0px"
})
createElement('div', 'left', {
position: 'fixed',
width: '80px',
height: '80px',
backgroundColor: 'blue',
left: '30px',
bottom: '30px'
}, {
mousedown: () => {
this.doAction('left')
},
mouseup: () => {
this.cancelAction('left')
},
touchstart: (e) => {
const target = e.target as HTMLElement & {
touchColor: string,
originColor: string
}
target.style.backgroundColor = target.touchColor
this.doAction('left')
},
touchend: (e) => {
const target = e.target as HTMLElement & {
touchColor: string,
originColor: string
}
target.style.backgroundColor = target.originColor
this.cancelAction('left')
}
})
createElement('div', 'right', {
position: 'fixed',
width: '80px',
height: '80px',
backgroundColor: 'blue',
left: '130px',
bottom: '30px'
}, {
mousedown: () => {
this.doAction('right')
},
mouseup: () => {
this.cancelAction('right')
},
touchstart: (e) => {
const target = e.target as HTMLElement & {
touchColor: string,
originColor: string
}
target.style.backgroundColor = target.touchColor
this.doAction('right')
},
touchend: (e) => {
const target = e.target as HTMLElement & {
touchColor: string,
originColor: string
}
target.style.backgroundColor = target.originColor
this.cancelAction('right')
}
})
createElement('div', 'acceleration', {
position: 'fixed',
width: '80px',
height: '80px',
backgroundColor: 'blue',
right: '130px',
bottom: '30px'
}, {
mousedown: () => {
this.doAction('acceleration')
},
mouseup: () => {
this.cancelAction('acceleration')
},
touchstart: (e) => {
const target = e.target as HTMLElement & {
touchColor: string,
originColor: string
}
target.style.backgroundColor = target.touchColor
this.doAction('acceleration')
},
touchend: (e) => {
const target = e.target as HTMLElement & {
touchColor: string,
originColor: string
}
target.style.backgroundColor = target.originColor
this.cancelAction('acceleration')
}
})
createElement('div', 'braking', {
position: 'fixed',
width: '80px',
height: '80px',
backgroundColor: 'blue',
right: '30px',
bottom: '30px'
}, {
mousedown: () => {
this.doAction('braking')
},
mouseup: () => {
this.cancelAction('braking')
},
touchstart: (e) => {
const target = e.target as HTMLElement & {
touchColor: string,
originColor: string
}
target.style.backgroundColor = target.touchColor
this.doAction('braking')
},
touchend: (e) => {
const target = e.target as HTMLElement & {
touchColor: string,
originColor: string
}
target.style.backgroundColor = target.originColor
this.cancelAction('braking')
}
})
} }
...@@ -301,10 +166,10 @@ export class Vehicle extends PreloadGroup{ ...@@ -301,10 +166,10 @@ export class Vehicle extends PreloadGroup{
wheelInfo.set_m_rollInfluence(rollInfluence); wheelInfo.set_m_rollInfluence(rollInfluence);
this.wheelMeshes[index] = this.createWheelMesh(radius, width); this.wheelMeshes[index] = this.createWheelMesh(radius, width, pos);
} }
createWheelMesh = (radius: number, width: number) => { createWheelMesh = (radius: number, width: number, pos: Ammo.btVector3) => {
const group = new THREE.Group() const group = new THREE.Group()
var t = new THREE.CylinderGeometry(radius, radius, width, 24, 1); var t = new THREE.CylinderGeometry(radius, radius, width, 24, 1);
t.rotateZ(Math.PI / 2); t.rotateZ(Math.PI / 2);
...@@ -317,6 +182,7 @@ export class Vehicle extends PreloadGroup{ ...@@ -317,6 +182,7 @@ export class Vehicle extends PreloadGroup{
luntai.visible = !VehicleDebugConfig.debugger luntai.visible = !VehicleDebugConfig.debugger
group.add(luntai) group.add(luntai)
this.add(group) this.add(group)
group.position.set(pos.x(), pos.y(), pos.z())
return group; return group;
} }
...@@ -396,9 +262,8 @@ export class Vehicle extends PreloadGroup{ ...@@ -396,9 +262,8 @@ export class Vehicle extends PreloadGroup{
const tuning = this.btVehicleTuning const tuning = this.btVehicleTuning
// vehicle.updateFriction(delta) // vehicle.updateFriction(delta)
var speed = vehicle.getCurrentSpeedKmHour(); // 记录当前速度
const speed = this.speedNum = vehicle.getCurrentSpeedKmHour();
this.sppedBoard.innerHTML = (speed < 0 ? '(R) ' : '') + Math.abs(speed).toFixed(1) + ' km/h';
let breakingForce = 0; let breakingForce = 0;
let engineForce = 0; let engineForce = 0;
......
export const ResJson = { export const ResJson = {
"groups": [ "groups": [
{
"keys": "brake-icon.png,camera-icon.png,engine-icon.png,left-icon.png,reset-icon.png,right-icon.png",
"name": "UI"
},
{ {
"keys": "luntai.gltf,qiche_V6.gltf,shamo_V10.gltf", "keys": "luntai.gltf,qiche_V6.gltf,shamo_V10.gltf",
"name": "gltf" "name": "gltf"
......
...@@ -2,20 +2,43 @@ import { CarScene } from "./CarScene" ...@@ -2,20 +2,43 @@ import { CarScene } from "./CarScene"
import * as THREE from 'three' import * as THREE from 'three'
import { RES } from "./module/RES" import { RES } from "./module/RES"
import { ResJson } from "./ResJson" import { ResJson } from "./ResJson"
import { EventDispatcher } from "./module/EventDispatcher"
window['THREE'] = THREE window['THREE'] = THREE
export class StageScene { export class StageScene {
renderDom: HTMLCanvasElement
stage: CarScene
UIParentNode: HTMLElement
constructor( constructor(
canvas?: HTMLCanvasElement canvas: HTMLCanvasElement,
UIParentNode: HTMLElement
) { ) {
this.initStage(canvas) this.renderDom = canvas
this.UIParentNode = UIParentNode
this.initStage()
} }
async initStage(dom?: HTMLCanvasElement) { async initStage() {
RES.loadConfig(ResJson) RES.loadConfig(ResJson)
new CarScene(dom) // @ts-ignore
Ammo().then(() => {
this.stage = new CarScene(this.renderDom, this.UIParentNode)
})
} }
}
\ No newline at end of file destroy() {
this.stage.destroy()
}
}
type GDType = {
'orientationChange': {
isPortrait: boolean // 是否是竖屏
}
}
export const GDispather = new EventDispatcher<keyof GDType>()
\ No newline at end of file
...@@ -3,7 +3,6 @@ type EventCall<T extends any> = (e?: { ...@@ -3,7 +3,6 @@ type EventCall<T extends any> = (e?: {
data: any data: any
}, ...arg1: any[]) => any }, ...arg1: any[]) => any
export class EventDispatcher<EventsKeyName extends string = string> { export class EventDispatcher<EventsKeyName extends string = string> {
private listeners: { private listeners: {
[key in EventsKeyName]?: { [key in EventsKeyName]?: {
...@@ -42,6 +41,10 @@ export class EventDispatcher<EventsKeyName extends string = string> { ...@@ -42,6 +41,10 @@ export class EventDispatcher<EventsKeyName extends string = string> {
// } // }
} }
removeAllEventListener() {
this.listeners = Object.create(null)
}
onceEventListener(type: EventsKeyName, listener: EventCall<EventsKeyName>, context?: any) { onceEventListener(type: EventsKeyName, listener: EventCall<EventsKeyName>, context?: any) {
const once = (...args: any[]) => { const once = (...args: any[]) => {
listener.apply(context, args) listener.apply(context, args)
...@@ -54,7 +57,8 @@ export class EventDispatcher<EventsKeyName extends string = string> { ...@@ -54,7 +57,8 @@ export class EventDispatcher<EventsKeyName extends string = string> {
if (!this.listeners[type]) { if (!this.listeners[type]) {
return return
} }
this.listeners[type]!.forEach(item => { const array = this.listeners[type].slice(0)
array.forEach(item => {
const { const {
listener, listener,
context context
......
// type BaseEventMap = {
// [eventName: string]: any
// }
// type BaseEvent = {
// type: string
// }
// type AddRecordArgs2<T extends Record<string, any>, E extends >
// /**
// * Event object.
// */
// export interface Event extends BaseEvent {
// target?: any;
// [attachment: string]: any;
// }
// export class NewEventDispatcher<E extends BaseEventMap> {
// }
\ No newline at end of file
...@@ -100,11 +100,9 @@ export class PerspectiveScene extends ScenePreloadGroup { ...@@ -100,11 +100,9 @@ export class PerspectiveScene extends ScenePreloadGroup {
// _renderer.shadowMap.enabled = true // _renderer.shadowMap.enabled = true
// _renderer.shadowMap.type = PCFShadowMap // _renderer.shadowMap.type = PCFShadowMap
_renderer.setSize(window.innerWidth, window.innerHeight) _renderer.setSize(window.innerWidth, window.innerHeight)
// this.camera.updateProjectionMatrix()
// _renderer.setViewport(0, 0, 812, 375)
_renderer.setPixelRatio(window.devicePixelRatio) _renderer.setPixelRatio(window.devicePixelRatio)
_renderer.outputEncoding = sRGBEncoding; _renderer.outputEncoding = sRGBEncoding;
document.body.appendChild(_renderer.domElement) // document.body.appendChild(_renderer.domElement)
} }
...@@ -123,7 +121,7 @@ export class PerspectiveScene extends ScenePreloadGroup { ...@@ -123,7 +121,7 @@ export class PerspectiveScene extends ScenePreloadGroup {
/** /**
* 清除事件 * 清除事件
*/ */
private removeEvents() { private __removeEvents() {
window.removeEventListener('resize', this.onWindowResize) window.removeEventListener('resize', this.onWindowResize)
} }
...@@ -137,6 +135,7 @@ export class PerspectiveScene extends ScenePreloadGroup { ...@@ -137,6 +135,7 @@ export class PerspectiveScene extends ScenePreloadGroup {
this.renderer.setSize(window.innerWidth, window.innerHeight) this.renderer.setSize(window.innerWidth, window.innerHeight)
} }
requestId: number
/** /**
* 帧循环 * 帧循环
*/ */
...@@ -149,6 +148,12 @@ export class PerspectiveScene extends ScenePreloadGroup { ...@@ -149,6 +148,12 @@ export class PerspectiveScene extends ScenePreloadGroup {
// frame rander // frame rander
this.renderer.render(this.scene, this.camera) this.renderer.render(this.scene, this.camera)
this.OrbitControlsIns.update() this.OrbitControlsIns.update()
requestAnimationFrame(this.frameLoop.bind(this)) this.requestId = requestAnimationFrame(this.frameLoop.bind(this))
}
destroy() {
cancelAnimationFrame(this.requestId)
this.__removeEvents()
this.removeAllEventListener()
} }
} }
\ No newline at end of file
...@@ -455,7 +455,7 @@ export namespace RES { ...@@ -455,7 +455,7 @@ export namespace RES {
* @param str * @param str
* @return 已加载好得素材或null * @return 已加载好得素材或null
*/ */
export function getRes(str: `${string}.${'png' | 'jpg' | 'gltf'}`)/*: Texture | VideoEntity*/ { export function getRes(str: `${string}.${'png' | 'jpg' | 'gltf'}` | string)/*: Texture | VideoEntity*/ {
if (!str) return null; if (!str) return null;
var type = str.substring(str.lastIndexOf(".") + 1, str.length); var type = str.substring(str.lastIndexOf(".") + 1, str.length);
if (type == "png" || type == "jpg") { if (type == "png" || type == "jpg") {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment