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

dom 操作添加

parent 0ea1b78f
......@@ -99,13 +99,16 @@
height: 375px !important;
display: block; */
/* transform: rotate(90deg);
transform-origin: center center; */
transform-origin: calc(100vw / 2) calc(100vw / 2); */
}
</style>
<script src="//yun.duiba.com.cn/aurora/assets/4723050c150b41f362ecf483e9cf98eb31c4a15b.js"></script>
</head>
<body>
<canvas id="stage"></canvas>
<div class="ss">
<canvas id="stage"></canvas>
</div>
<div id="test"></div>
<script type="importmap">
{
"imports": {
......@@ -124,11 +127,9 @@
window['hideLoading'] = function() {
document.querySelector('.load-container').style.display = 'none'
}
Ammo().then(() => {
const dome = document.getElementById('stage')
new StageScene(dome)
})
console.log(Ammo)
const dome = document.getElementById('stage')
new StageScene(dome)
})
</script>
......
......@@ -62662,6 +62662,118 @@ Stats.Panel = function ( name, fg, bg ) {
/* 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":
......@@ -62710,6 +62822,10 @@ const GLTFLoader_1 = __webpack_require__(/*! ../module/loaders/GLTFLoader */ "./
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 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) {
var c = document.createElement("canvas");
var ct = c.getContext("2d");
......@@ -62759,14 +62875,57 @@ function basicTexture(n) {
const GeometryMap = {
'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);
const GLTFLoaderIns = new GLTFLoader_1.GLTFLoader();
const _defaultVector3 = new THREE.Vector3();
const _rayCaster = new THREE.Raycaster();
const _v3 = new THREE.Vector3();
class CarScene extends PerspectiveScene_1.PerspectiveScene {
constructor() {
super();
constructor(d) {
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.far = 400;
this.OrbitControlsIns.enabled = false;
......@@ -62776,12 +62935,19 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
// document.body.addEventListener('click', () => {
// this.cameraControls.lock()
// })
this.cameraPos = GameConfig_1.GameConfig.CameraPosConfig.change();
this.initStats();
this.initEvents();
this.initRenderer();
}
get groupNames() {
return ['gltf', 'skybox'];
}
// 初始化 render
initRenderer() {
this.init2DUi();
this.onDeviceOrientationChange();
}
initStats() {
const statsIns = (0, stats_module_1.default)();
console.log('===========Stats: ============\n', statsIns);
......@@ -62796,10 +62962,20 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
});
}
ViewDraw() {
const reflectionCube = new THREE.CubeTextureLoader()
.setPath('/resource/skybox/')
.load(['px1.jpg', 'nx1.jpg', 'py1.jpg', 'ny1.jpg', 'pz1.jpg', 'nz1.jpg']);
const reflectionCube = new THREE.CubeTexture();
const map = {
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.needsUpdate = true;
this.scene.background = reflectionCube;
// let pmremGenerator = new THREE.PMREMGenerator(this.renderer)
// pmremGenerator.compileEquirectangularShader();
......@@ -62811,7 +62987,6 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
dirLight.castShadow = true;
dirLight.position.set(20, 20, 20);
this.scene.add(dirLight);
this.scene.add(new THREE.DirectionalLightHelper(dirLight));
this.scene.add(new THREE.AmbientLight(0x222222, 1));
dirLight.castShadow = true;
console.log(dirLight.shadow);
......@@ -62824,7 +62999,6 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
dirLight.shadow.camera.bottom = -20;
dirLight.shadow.camera.right = -20;
dirLight.shadow.radius = 4;
this.scene.add(new THREE.CameraHelper(dirLight.shadow.camera));
let renderer = this.renderer;
// 开启阴影
renderer.shadowMap.enabled = true;
......@@ -62834,14 +63008,207 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
// THREE.VSMShadowMap-性能差,约束多,但能够产生意想不到的效果。
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
this.scene.add(new THREE.AmbientLight(0x3D4143));
this.scene.add(new THREE.AxesHelper(100));
this.scene.add(new THREE.GridHelper(100, 20));
if (GameConfig_1.GameConfig.helperDebuger) {
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')
// // @ts-ignore
// window['imgTexture'] = imgTexture
// console.log('=======imgTexture=======', imgTexture, imgTexture.image)
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() {
const wallList = [
{
......@@ -62907,8 +63274,6 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
}
});
this.terrainMesh = terrainMesh;
// @ts-ignore
window['terrainMesh'] = terrainMesh;
if (terrainMesh) {
terrainMesh.receiveShadow = true;
// terrainMesh.castShadow = true
......@@ -62935,7 +63300,7 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
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.ammoPhysicWorld.addDynamicBody(vehicleIns);
// @ts-ignore
......@@ -62964,75 +63329,60 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
// mass: 0
// }
// ))
// 下面是测试模型数据
const boxGeometry = new THREE.BoxGeometry(1, 1, 1, 10, 10, 10);
const material = new THREE.MeshLambertMaterial({
// 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);
if (GameConfig_1.GameConfig.collisionDebuger) {
// 下面是测试模型数据
const boxGeometry = new THREE.BoxGeometry(1, 1, 1, 10, 10, 10);
const material = new THREE.MeshLambertMaterial({
// wireframe: true,
// 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);
boxMesh.position.set(-Math.random() * 20, 10, -Math.random() * 20);
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.addMesh(boxMesh, {
mass: 1,
// friction: 10,
restitution: 1
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)
}));
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({
// length: 10
// }, (_, index) => {
......@@ -63121,12 +63471,26 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
};
}
initEvents() {
this.addEventListener(PerspectiveScene_1.EVENTS_ENUM.ENTERFRAME, this.updateOimoPhysics, 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) {
const delta = e.data.delta;
if (this.physicWorld) {
this.physicWorld.step();
}
......@@ -63134,6 +63498,44 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
this.ammoPhysicWorld.step();
}
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) {
if (this.vehicleIns && !this.OrbitControlsIns.enabled) {
......@@ -63141,14 +63543,14 @@ class CarScene extends PerspectiveScene_1.PerspectiveScene {
// 跟随 Car
// 0, 8, -20
// 0, 20, -16
_defaultVector3.set(0, 8, -20);
_defaultVector3.copy(this.cameraPos);
// @ts-ignore
window['vehicle'] || (window['vehicle'] = this.vehicleIns.chassisMesh);
// const m3 = new THREE.Matrix3()
// relativeCameraOffset.applyMatrix3(m3.setFromMatrix4(this.vehicleIns.chassisMesh.matrixWorld))
const vehiclePosition = this.vehicleIns.chassisMesh.position;
_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);
_rayCaster.near = 0;
_rayCaster.far = _v3.length();
......@@ -63480,7 +63882,7 @@ class Vehicle extends PreloadGroup_1.PreloadGroup {
constructor(pos, quat) {
super();
this.wheelMeshes = [];
this.createWheelMesh = (radius, width) => {
this.createWheelMesh = (radius, width, pos) => {
const group = new THREE.Group();
var t = new THREE.CylinderGeometry(radius, radius, width, 24, 1);
t.rotateZ(Math.PI / 2);
......@@ -63493,6 +63895,7 @@ class Vehicle extends PreloadGroup_1.PreloadGroup {
luntai.visible = !VehicleDebugConfig.debugger;
group.add(luntai);
this.add(group);
group.position.set(pos.x(), pos.y(), pos.z());
return group;
};
// Raycast Vehicle
......@@ -63553,113 +63956,6 @@ class Vehicle extends PreloadGroup_1.PreloadGroup {
// new THREE.BoxGeometry(1, 1, 1),
// 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 {
wheelInfo.set_m_wheelsDampingCompression(suspensionCompression);
wheelInfo.set_m_frictionSlip(friction); // 摩擦系数
wheelInfo.set_m_rollInfluence(rollInfluence);
this.wheelMeshes[index] = this.createWheelMesh(radius, width);
this.wheelMeshes[index] = this.createWheelMesh(radius, width, pos);
}
createChassisMesh(w, l, h) {
const group = new THREE.Group();
......@@ -63736,8 +64032,8 @@ class Vehicle extends PreloadGroup_1.PreloadGroup {
const vehicle = this.raycastVehicle;
const tuning = this.btVehicleTuning;
// 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 engineForce = 0;
const isAccelerating = this.actions.acceleration || keyboardState_1.KeyBoardStateStore.isPressed('w');
......@@ -63948,6 +64244,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.ResJson = void 0;
exports.ResJson = {
"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",
"name": "gltf"
......@@ -63958,7 +64258,7 @@ exports.ResJson = {
}
],
// 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
});
};
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 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 ResJson_1 = __webpack_require__(/*! ./ResJson */ "./src/ResJson.ts");
const EventDispatcher_1 = __webpack_require__(/*! ./module/EventDispatcher */ "./src/module/EventDispatcher.ts");
window['THREE'] = THREE;
class StageScene {
constructor() {
constructor(canvas) {
this.renderDom = canvas;
this.initStage();
}
initStage() {
return __awaiter(this, void 0, void 0, function* () {
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.GDispather = new EventDispatcher_1.EventDispatcher();
/***/ }),
......@@ -64261,6 +64570,9 @@ class EventDispatcher {
// this.listeners[type]!.splice(index, 1)
// }
}
removeAllEventListener() {
this.listeners = Object.create(null);
}
onceEventListener(type, listener, context) {
const once = (...args) => {
listener.apply(context, args);
......@@ -64272,7 +64584,8 @@ class EventDispatcher {
if (!this.listeners[type]) {
return;
}
this.listeners[type].forEach(item => {
const array = this.listeners[type].slice(0);
array.forEach(item => {
const { listener, context } = item;
listener.call(context, {
type,
......@@ -65123,7 +65436,7 @@ class ScenePreloadGroup extends EventDispatcher_1.EventDispatcher {
ViewDraw() { }
}
class PerspectiveScene extends ScenePreloadGroup {
constructor() {
constructor(canvasDom) {
super();
/**
* window resize
......@@ -65134,6 +65447,7 @@ class PerspectiveScene extends ScenePreloadGroup {
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
};
this.renderCanvasElement = canvasDom;
this.clock = new three_1.Clock();
this.__initScene();
this.__initCamera();
......@@ -65153,7 +65467,7 @@ class PerspectiveScene extends ScenePreloadGroup {
this.scene.add(_camera);
}
__initRenderer() {
const matrialSceneCanvas = this.rendererDom = document.createElement('canvas');
const matrialSceneCanvas = this.rendererDom = this.renderCanvasElement || document.createElement('canvas');
matrialSceneCanvas.style.display = 'block';
const _renderer = this.renderer = new three_1.WebGLRenderer({
canvas: matrialSceneCanvas,
......@@ -65164,7 +65478,7 @@ class PerspectiveScene extends ScenePreloadGroup {
_renderer.setSize(window.innerWidth, window.innerHeight);
_renderer.setPixelRatio(window.devicePixelRatio);
_renderer.outputEncoding = three_1.sRGBEncoding;
document.body.appendChild(_renderer.domElement);
// document.body.appendChild(_renderer.domElement)
}
/**
* 初始化事件
......@@ -65172,12 +65486,12 @@ class PerspectiveScene extends ScenePreloadGroup {
__initEvents() {
const OrbitControlsIns = this.OrbitControlsIns = new index_1.OrbitControls(this.camera, this.rendererDom);
this.frameLoop();
window.addEventListener('resize', this.onWindowResize);
// window.addEventListener('resize', this.onWindowResize)
}
/**
* 清除事件
*/
removeEvents() {
__removeEvents() {
window.removeEventListener('resize', this.onWindowResize);
}
/**
......@@ -65191,7 +65505,12 @@ class PerspectiveScene extends ScenePreloadGroup {
// frame rander
this.renderer.render(this.scene, this.camera);
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;
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -6,6 +6,7 @@
"scripts": {
"dev": "node ./scripts/devServer -p 9016",
"build": "webpack --config webpack.prod.js",
"flushRes": "node scripts/flushRes",
"handleRes": "node scripts/delRel && node scripts/copyRes && node scripts/imageMin",
"upload": "node scripts/upload",
"prod": "npm run handleRes && npm run upload && npm run buildTS",
......
{
"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",
"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";
import Stats from 'three/examples/jsm/libs/stats.module'
import { RoomEnvironment } from '../module/environment/RoomEnvironment';
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[]]) {
var c = document.createElement("canvas");
......@@ -61,6 +65,13 @@ const GeometryMap = {
'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);
const GLTFLoaderIns = new GLTFLoader()
......@@ -74,12 +85,13 @@ export class CarScene extends PerspectiveScene {
cameraControls: FirstPersonCameraControl
dirLight: THREE.DirectionalLight
terrainMesh: THREE.Mesh
cameraPos: THREE.Vector3
get groupNames(): string[] {
return ['gltf', 'skybox']
}
constructor(d: HTMLCanvasElement) {
constructor(d: HTMLCanvasElement, u: HTMLElement) {
super(d)
this.camera.position.set(20, 20, 20)
......@@ -92,9 +104,20 @@ export class CarScene extends PerspectiveScene {
// document.body.addEventListener('click', () => {
// this.cameraControls.lock()
// })
this.cameraPos = GameConfig.CameraPosConfig.change()
this.initStats()
this.initEvents()
this.init2DUi(u)
this.initRenderer()
}
// 初始化 render
initRenderer() {
this.onDeviceOrientationChange()
}
initStats() {
......@@ -113,11 +136,20 @@ export class CarScene extends PerspectiveScene {
}
ViewDraw() {
this.camera.rotateZ(Math.PI / 2)
const reflectionCube = new THREE.CubeTextureLoader()
.setPath( '/resource/skybox/' )
.load( [ 'px1.jpg', 'nx1.jpg', 'py1.jpg', 'ny1.jpg', 'pz1.jpg', 'nz1.jpg' ] );
const reflectionCube = new THREE.CubeTexture()
const map: Record<string, string> = {
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.getRes(map[(k)]).image
}
reflectionCube.encoding = THREE.sRGBEncoding;
reflectionCube.needsUpdate = true
this.scene.background = reflectionCube;
// let pmremGenerator = new THREE.PMREMGenerator(this.renderer)
......@@ -132,7 +164,6 @@ export class CarScene extends PerspectiveScene {
dirLight.castShadow = true
dirLight.position.set(20, 20, 20)
this.scene.add(dirLight)
this.scene.add(new THREE.DirectionalLightHelper(dirLight))
this.scene.add(new THREE.AmbientLight(0x222222, 1))
......@@ -148,8 +179,6 @@ export class CarScene extends PerspectiveScene {
dirLight.shadow.camera.right = -20
dirLight.shadow.radius = 4
this.scene.add(new THREE.CameraHelper(dirLight.shadow.camera))
let renderer = this.renderer
// 开启阴影
renderer.shadowMap.enabled = true
......@@ -161,8 +190,13 @@ export class CarScene extends PerspectiveScene {
this.scene.add(new THREE.AmbientLight(0x3D4143))
this.scene.add(new THREE.AxesHelper(100))
this.scene.add(new THREE.GridHelper(100, 20))
if (GameConfig.helperDebuger) {
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')
// // @ts-ignore
......@@ -173,6 +207,234 @@ export class CarScene extends PerspectiveScene {
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() {
const wallList: {
rotationDeg: number,
......@@ -261,8 +523,6 @@ export class CarScene extends PerspectiveScene {
}
})
this.terrainMesh = terrainMesh
// @ts-ignore
window['terrainMesh'] = terrainMesh
if (terrainMesh) {
terrainMesh.receiveShadow = true
// terrainMesh.castShadow = true
......@@ -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.ammoPhysicWorld.addDynamicBody(vehicleIns)
// @ts-ignore
......@@ -315,6 +575,8 @@ export class CarScene extends PerspectiveScene {
// @ts-ignore
planeMesh.material = terrainMesh.material
this.scene.add(planeMesh)
// this.ammoPhysicWorld.addMesh(planeMesh, {
// friction: 10,
// restitution: 0.1,
......@@ -327,90 +589,71 @@ export class CarScene extends PerspectiveScene {
// }
// ))
// 下面是测试模型数据
const boxGeometry = new THREE.BoxGeometry(1,1,1, 10, 10, 10)
const material = new THREE.MeshLambertMaterial({
// 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)
if (GameConfig.collisionDebuger) {
// 下面是测试模型数据
const boxGeometry = new THREE.BoxGeometry(1,1,1, 10, 10, 10)
const material = new THREE.MeshLambertMaterial({
// wireframe: true,
// 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)
boxMesh.position.set(-Math.random() * 20, 10, -Math.random() * 20)
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)
this.ammoPhysicWorld.addMesh(boxMesh, {
mass: 1,
// friction: 10,
restitution: 1
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)
}
))
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({
// length: 10
......@@ -509,15 +752,78 @@ export class CarScene extends PerspectiveScene {
}
initEvents() {
this.addEventListener(EVENTS_ENUM.ENTERFRAME, this.updateOimoPhysics, 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) {
const delta = e.data.delta
if (this.physicWorld) {
this.physicWorld.step()
}
......@@ -527,6 +833,49 @@ export class CarScene extends PerspectiveScene {
}
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) {
......@@ -535,14 +884,14 @@ export class CarScene extends PerspectiveScene {
// 跟随 Car
// 0, 8, -20
// 0, 20, -16
_defaultVector3.set(0, 8, -20)
_defaultVector3.copy(this.cameraPos)
// @ts-ignore
window['vehicle'] || (window['vehicle'] = this.vehicleIns.chassisMesh)
// const m3 = new THREE.Matrix3()
// relativeCameraOffset.applyMatrix3(m3.setFromMatrix4(this.vehicleIns.chassisMesh.matrixWorld))
const vehiclePosition = this.vehicleIns.chassisMesh.position
_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)
_rayCaster.near = 0
_rayCaster.far = _v3.length()
......
......@@ -64,10 +64,11 @@ export class Vehicle extends PreloadGroup{
chassisRidigBody: Ammo.btRigidBody
raycastVehicle: Ammo.btRaycastVehicle
btVehicleTuning: Ammo.btVehicleTuning
sppedBoard: HTMLElement // 速度面板
luntaiIns: GltfModel // 轮胎模型
speedNum: number
constructor(pos: THREE.Vector3, quat: THREE.Quaternion) {
super()
......@@ -122,142 +123,6 @@ export class Vehicle extends PreloadGroup{
// new THREE.BoxGeometry(1, 1, 1),
// 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{
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()
var t = new THREE.CylinderGeometry(radius, radius, width, 24, 1);
t.rotateZ(Math.PI / 2);
......@@ -317,6 +182,7 @@ export class Vehicle extends PreloadGroup{
luntai.visible = !VehicleDebugConfig.debugger
group.add(luntai)
this.add(group)
group.position.set(pos.x(), pos.y(), pos.z())
return group;
}
......@@ -396,9 +262,8 @@ export class Vehicle extends PreloadGroup{
const tuning = this.btVehicleTuning
// 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 engineForce = 0;
......
export const ResJson = {
"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",
"name": "gltf"
......
......@@ -2,20 +2,43 @@ import { CarScene } from "./CarScene"
import * as THREE from 'three'
import { RES } from "./module/RES"
import { ResJson } from "./ResJson"
import { EventDispatcher } from "./module/EventDispatcher"
window['THREE'] = THREE
export class StageScene {
renderDom: HTMLCanvasElement
stage: CarScene
UIParentNode: HTMLElement
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)
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?: {
data: any
}, ...arg1: any[]) => any
export class EventDispatcher<EventsKeyName extends string = string> {
private listeners: {
[key in EventsKeyName]?: {
......@@ -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) {
const once = (...args: any[]) => {
listener.apply(context, args)
......@@ -54,7 +57,8 @@ export class EventDispatcher<EventsKeyName extends string = string> {
if (!this.listeners[type]) {
return
}
this.listeners[type]!.forEach(item => {
const array = this.listeners[type].slice(0)
array.forEach(item => {
const {
listener,
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 {
// _renderer.shadowMap.enabled = true
// _renderer.shadowMap.type = PCFShadowMap
_renderer.setSize(window.innerWidth, window.innerHeight)
// this.camera.updateProjectionMatrix()
// _renderer.setViewport(0, 0, 812, 375)
_renderer.setPixelRatio(window.devicePixelRatio)
_renderer.outputEncoding = sRGBEncoding;
document.body.appendChild(_renderer.domElement)
// document.body.appendChild(_renderer.domElement)
}
......@@ -123,7 +121,7 @@ export class PerspectiveScene extends ScenePreloadGroup {
/**
* 清除事件
*/
private removeEvents() {
private __removeEvents() {
window.removeEventListener('resize', this.onWindowResize)
}
......@@ -137,6 +135,7 @@ export class PerspectiveScene extends ScenePreloadGroup {
this.renderer.setSize(window.innerWidth, window.innerHeight)
}
requestId: number
/**
* 帧循环
*/
......@@ -149,6 +148,12 @@ export class PerspectiveScene extends ScenePreloadGroup {
// frame rander
this.renderer.render(this.scene, this.camera)
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 {
* @param str
* @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;
var type = str.substring(str.lastIndexOf(".") + 1, str.length);
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