CScenario.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. function CScenario() {
  2. var _oWorld;
  3. var _oGroundMaterial;
  4. var _oBallMaterial;
  5. var _oWallMaterial;
  6. var _oPinMaterial;
  7. var _oBallShape;
  8. var _oBallBody;
  9. var _oBallMesh;
  10. var _oTrackBody;
  11. var _oChannelLeftBody;
  12. var _oChannelRightBody;
  13. var _oPinFloorBody;
  14. var _oPinWallForwardBody;
  15. var _oBodyWallPins;
  16. var _oBodyDepthTrack;
  17. var _oPinsBinderBody;
  18. var _oSideWallBody;
  19. var _oSensorPinFloor;
  20. var _aPin;
  21. var _aSidesPinsFloor;
  22. if (SHOW_3D_RENDER)
  23. var _oDemo = new CANNON.Demo();
  24. this.getDemo = function () {
  25. return _oDemo;
  26. };
  27. this._init = function () {
  28. _aPin = new Array();
  29. _aSidesPinsFloor = new Array();
  30. if (SHOW_3D_RENDER) {
  31. _oWorld = _oDemo.getWorld();
  32. } else {
  33. _oWorld = new CANNON.World();
  34. }
  35. var oSolver = new CANNON.GSSolver();
  36. oSolver.iterations = 10;
  37. oSolver.tolerance = 0.0001;
  38. _oWorld.allowSleep = true;
  39. _oWorld.gravity.set(0, 0, -(19.52 * STEP_RATE));
  40. _oWorld.broadphase = new CANNON.NaiveBroadphase();
  41. _oWorld.solver = new CANNON.SplitSolver(oSolver, 20, 0.0001);
  42. _oGroundMaterial = new CANNON.Material();
  43. _oBallMaterial = new CANNON.Material();
  44. _oWallMaterial = new CANNON.Material();
  45. _oPinMaterial = new CANNON.Material();
  46. var oWallBallCm = new CANNON.ContactMaterial(
  47. _oBallMaterial, _oWallMaterial, {
  48. friction: 0.1,
  49. restitution: 0.1
  50. });
  51. var oGroundBallCm = new CANNON.ContactMaterial(
  52. _oBallMaterial, _oGroundMaterial, {
  53. friction: 0.01,
  54. restitution: 0.1
  55. });
  56. var oPinBallCm = new CANNON.ContactMaterial(
  57. _oBallMaterial, _oPinMaterial, {
  58. friction: 0.1,
  59. restitution: 0.3
  60. });
  61. var oPinGroundCm = new CANNON.ContactMaterial(
  62. _oGroundMaterial, _oPinMaterial, {
  63. friction: 0.2,
  64. restitution: 0.3
  65. });
  66. var oPinPinCm = new CANNON.ContactMaterial(
  67. _oPinMaterial, _oPinMaterial, {
  68. friction: 0.01,
  69. restitution: 0.1
  70. });
  71. var oPinWallCm = new CANNON.ContactMaterial(
  72. _oPinMaterial, _oWallMaterial, {
  73. friction: 0.01,
  74. restitution: 0.1
  75. });
  76. _oWorld.addContactMaterial(oWallBallCm);
  77. _oWorld.addContactMaterial(oGroundBallCm);
  78. _oWorld.addContactMaterial(oPinBallCm);
  79. _oWorld.addContactMaterial(oPinGroundCm);
  80. _oWorld.addContactMaterial(oPinPinCm);
  81. _oWorld.addContactMaterial(oPinWallCm);
  82. s_oScenario._createBallBody();
  83. for (var i = 0; i < PINS_POSITION.length; i++) {
  84. _aPin[i] = s_oScenario.createPin(PINS_POSITION[i], i, false);
  85. }
  86. s_oScenario.importFBXTrack();
  87. s_oScenario.createWallPins();
  88. s_oScenario.createFloorPins();
  89. s_oScenario.createPinsBinder();
  90. s_oScenario.createWallFloorPins();
  91. s_oScenario.createSideWallTrack();
  92. s_oScenario.createSensorPinFloor();
  93. if (SHOW_DEPTH_TRACK_MODEL) {
  94. s_oScenario.createDepthTrack();
  95. }
  96. if (PIN_TEST) {
  97. _aPin.push(s_oScenario.createPin(PINS_PROPERTIES_TEST, -1, true));
  98. }
  99. var fOffsetXLeft = FLOOR_PINS_SIZE.width + FLOOR_PINS_SIDE_PROPERTIES.width - 2.7;
  100. var oPosLeftFloor = {x: FLOOR_PINS_POSITION.x + fOffsetXLeft, y: FLOOR_PINS_POSITION.y, z: FLOOR_PINS_POSITION.z + FLOOR_PINS_SIZE.height - 9};
  101. _aSidesPinsFloor.push(s_oScenario.createAFloorSidePins(oPosLeftFloor, FLOOR_PINS_SIDE_PROPERTIES.rot));
  102. var fOffsetXRight = -FLOOR_PINS_SIZE.width - FLOOR_PINS_SIDE_PROPERTIES.width + 2.7;
  103. var oPosLeftRight = {x: FLOOR_PINS_POSITION.x + fOffsetXRight, y: FLOOR_PINS_POSITION.y, z: FLOOR_PINS_POSITION.z + FLOOR_PINS_SIZE.height - 9};
  104. _aSidesPinsFloor.push(s_oScenario.createAFloorSidePins(oPosLeftRight, -FLOOR_PINS_SIDE_PROPERTIES.rot));
  105. };
  106. this.importFBXTrack = function () {
  107. var manager = new THREE.LoadingManager();
  108. manager.onProgress = function (item, loaded, total) {
  109. console.log(item, loaded, total);
  110. };
  111. var onProgress = function (xhr) {
  112. if (xhr.lengthComputable) {
  113. var percentComplete = xhr.loaded / xhr.total * 100;
  114. console.log(Math.round(percentComplete, 2) + '% downloaded');
  115. }
  116. };
  117. var onError = function (xhr) {
  118. };
  119. var loader = new THREE.FBXLoader(manager);
  120. var oParent = this;
  121. loader.load('models/stage.txt', function (objects) {
  122. s_oScenario.parseFile(objects);
  123. objects = null;
  124. s_oGame.ballPosition();
  125. s_oGame.startPinsPosition();
  126. }, onProgress, onError);
  127. };
  128. this.parseFile = function (oFile) {
  129. for (var i = 0; i < oFile.children.length; i++) {
  130. var oMesh = oFile.children[i];
  131. console.log("oMesh.name: " + oMesh.name);
  132. if (oMesh.name === "floor") {
  133. _oTrackBody = s_oScenario._createFieldBody(oMesh, FLOOR);
  134. _oTrackBody.addEventListener("collide", function (e) {
  135. s_oScenario.floorCollision(e);
  136. });
  137. } else if (oMesh.name === "channel_left") {
  138. _oChannelLeftBody = s_oScenario._createFieldBody(oMesh, CHANNEL);
  139. _oChannelLeftBody.addEventListener("collide", function (e) {
  140. s_oScenario.channelCollision(e);
  141. });
  142. } else if (oMesh.name === "channel_right") {
  143. _oChannelRightBody = s_oScenario._createFieldBody(oMesh, CHANNEL);
  144. _oChannelRightBody.addEventListener("collide", function (e) {
  145. s_oScenario.channelCollision(e);
  146. });
  147. }
  148. }
  149. };
  150. this.createSensorPinFloor = function () {
  151. var oShapeWallPinsDown = new CANNON.Box(new CANNON.Vec3(SENSOR_SIZE.width, SENSOR_SIZE.depth, SENSOR_SIZE.height));
  152. _oSensorPinFloor = new CANNON.Body({mass: 0, material: _oWallMaterial, userData: {type: WALL}});
  153. _oSensorPinFloor.addShape(oShapeWallPinsDown);
  154. _oSensorPinFloor.addEventListener("collide", function (e) {
  155. s_oScenario.sensorCollision(e);
  156. });
  157. _oSensorPinFloor.position.set(SENSOR_POSITION.x, SENSOR_POSITION.y, SENSOR_POSITION.z);
  158. _oWorld.addBody(_oSensorPinFloor);
  159. if (SHOW_3D_RENDER) {
  160. var sensorMaterial = new THREE.MeshPhongMaterial({color: 0x550055, specular: 0x111111, shininess: 50});
  161. _oDemo.addVisual(_oSensorPinFloor, sensorMaterial);
  162. }
  163. };
  164. this.createAFloorSidePins = function (oPos, fRotY) {
  165. var oBody;
  166. var oShape = new CANNON.Box(new CANNON.Vec3(FLOOR_PINS_SIDE_PROPERTIES.width, FLOOR_PINS_SIDE_PROPERTIES.depth, FLOOR_PINS_SIDE_PROPERTIES.height));
  167. oBody = new CANNON.Body({mass: 0,
  168. material: _oGroundMaterial,
  169. userData: {type: PINS_FLOOR},
  170. collisionFilterGroup: PINS_FLOOR,
  171. collisionFilterMask: PINS});
  172. oBody.addShape(oShape);
  173. oBody.quaternion.y = fRotY;
  174. oBody.position.set(oPos.x, oPos.y, oPos.z);
  175. oBody.addEventListener("collide", function (e) {
  176. s_oScenario.sideWallCollision(e);
  177. });
  178. _oWorld.addBody(oBody);
  179. if (SHOW_3D_RENDER && SHOW_PROXY_COLLISION) {
  180. var sideMaterial = new THREE.MeshPhongMaterial({color: 0x008800, specular: 0x111111, shininess: 50});
  181. _oDemo.addVisual(oBody, sideMaterial);
  182. }
  183. return oBody;
  184. };
  185. this.createDepthTrack = function () {
  186. var oShapeDepthTrack = new CANNON.Box(new CANNON.Vec3(WALL_TRACK_DEPTH_SIZE.width, WALL_TRACK_DEPTH_SIZE.depth, WALL_TRACK_DEPTH_SIZE.height));
  187. _oBodyDepthTrack = new CANNON.Body({mass: 0,
  188. material: _oWallMaterial});
  189. _oBodyDepthTrack.collisionResponse = 0;
  190. _oBodyDepthTrack.addShape(oShapeDepthTrack);
  191. _oBodyDepthTrack.position.set(WALL_TRACK_DEPTH_POSITION.x, WALL_TRACK_DEPTH_POSITION.y, WALL_TRACK_DEPTH_POSITION.z);
  192. _oWorld.addBody(_oBodyDepthTrack);
  193. if (SHOW_3D_RENDER) {
  194. var depthMaterial = new THREE.MeshPhongMaterial({color: 0x888800, specular: 0x111111, shininess: 50});
  195. _oDemo.addVisual(_oBodyDepthTrack, depthMaterial);
  196. }
  197. };
  198. this.createFloorPins = function () {
  199. var oFloorShapePins = new CANNON.Box(new CANNON.Vec3(FLOOR_PINS_SIZE.width, FLOOR_PINS_SIZE.depth, FLOOR_PINS_SIZE.height));
  200. _oPinFloorBody = new CANNON.Body({mass: 0,
  201. material: _oGroundMaterial,
  202. userData: {type: PINS_FLOOR},
  203. collisionFilterGroup: PINS_FLOOR,
  204. collisionFilterMask: PINS});
  205. _oPinFloorBody.addShape(oFloorShapePins);
  206. _oPinFloorBody.position.set(FLOOR_PINS_POSITION.x, FLOOR_PINS_POSITION.y, FLOOR_PINS_POSITION.z);
  207. _oWorld.addBody(_oPinFloorBody);
  208. if (SHOW_3D_RENDER && SHOW_PROXY_COLLISION) {
  209. var floorMaterial = new THREE.MeshPhongMaterial({color: 0x000088, specular: 0x111111, shininess: 50});
  210. _oDemo.addVisual(_oPinFloorBody, floorMaterial);
  211. }
  212. };
  213. this.createWallFloorPins = function () {
  214. var oWallFloorShapePins = new CANNON.Box(new CANNON.Vec3(FLOOR_WALL_PINS_SIZE.width, FLOOR_WALL_PINS_SIZE.depth, FLOOR_WALL_PINS_SIZE.height));
  215. _oPinWallForwardBody = new CANNON.Body({mass: 0,
  216. material: _oGroundMaterial,
  217. userData: {type: PINS_FLOOR},
  218. collisionFilterGroup: PINS_FLOOR,
  219. collisionFilterMask: PINS});
  220. _oPinWallForwardBody.addShape(oWallFloorShapePins);
  221. _oPinWallForwardBody.position.set(FLOOR_WALL_PINS_POSITION.x, FLOOR_WALL_PINS_POSITION.y, FLOOR_WALL_PINS_POSITION.z);
  222. _oWorld.addBody(_oPinWallForwardBody);
  223. if (SHOW_3D_RENDER && SHOW_PROXY_COLLISION) {
  224. var wallMaterial = new THREE.MeshPhongMaterial({color: 0x880000, specular: 0xffff00, shininess: 10});
  225. _oDemo.addVisual(_oPinWallForwardBody, wallMaterial);
  226. }
  227. };
  228. this.createPinsBinder = function () {
  229. var oPinsBinderShape = new CANNON.Box(new CANNON.Vec3(PINS_BINDER_PROPERTIES.width, PINS_BINDER_PROPERTIES.depth, PINS_BINDER_PROPERTIES.height));
  230. _oPinsBinderBody = new CANNON.Body({mass: 0,
  231. material: _oWallMaterial,
  232. userData: {type: PINS_FLOOR},
  233. collisionFilterGroup: PINS_FLOOR,
  234. collisionFilterMask: PINS,
  235. fixedRotation: true,
  236. allowSleep: false,
  237. sleepTimeLimit: 1});
  238. _oPinsBinderBody.addShape(oPinsBinderShape);
  239. _oPinsBinderBody.position.set(PINS_BINDER_POSITION.x, PINS_BINDER_POSITION.y, PINS_BINDER_POSITION.z);
  240. _oWorld.addBody(_oPinsBinderBody);
  241. _oPinsBinderBody.collisionResponse = 0;
  242. if (SHOW_3D_RENDER) {
  243. var binderMaterial = new THREE.MeshPhongMaterial({color: 0x555555, specular: 0x111111, shininess: 50});
  244. _oDemo.addVisual(_oPinsBinderBody, binderMaterial);
  245. }
  246. };
  247. this._createFieldBody = function (oMesh, iType) {
  248. var oFieldMesh = this.__extractMeshData(oMesh);
  249. var oBody = new CANNON.Body({mass: 0, material: _oGroundMaterial, userData: {type: iType}});
  250. oBody.addShape(oFieldMesh);
  251. var v3IniPos = new CANNON.Vec3(oMesh.position.x + OFFSET_TRACK_POSITION.x, oMesh.position.y + OFFSET_TRACK_POSITION.y,
  252. oMesh.position.z + OFFSET_TRACK_POSITION.z);
  253. oBody.position.copy(v3IniPos);
  254. _oWorld.addBody(oBody);
  255. if (SHOW_3D_RENDER) {
  256. var fieldMaterial = new THREE.MeshPhongMaterial({color: 0xdeb887, specular: 0x000000, shininess: 100});
  257. _oDemo.addVisual(oBody, fieldMaterial);
  258. }
  259. return oBody;
  260. };
  261. this.__extractMeshData = function (oMesh) {
  262. var aRawFaces = oMesh.geometry.faces;
  263. var aRawVerts = oMesh.geometry.vertices;
  264. var aOnlyFaceCoord = new Array();
  265. for (var i = 0; i < aRawFaces.length; i++) {
  266. aOnlyFaceCoord[i] = {a: aRawFaces[i].a, b: aRawFaces[i].b, c: aRawFaces[i].c};
  267. }
  268. var verts = [], faces = [];
  269. var fScale = 1;
  270. ;
  271. // Get vertices
  272. for (var i = 0; i < aRawVerts.length; i++) {
  273. verts.push(aRawVerts[i].x * fScale);
  274. verts.push(aRawVerts[i].y * fScale);
  275. verts.push(aRawVerts[i].z * fScale);
  276. }
  277. // Get faces
  278. for (var i = 0; i < aRawFaces.length; i++) {
  279. faces.push(aRawFaces[i].a);
  280. faces.push(aRawFaces[i].b);
  281. faces.push(aRawFaces[i].c);
  282. }
  283. // Construct polyhedron
  284. return new CANNON.Trimesh(verts, faces);
  285. };
  286. this.createPin = function (oPos, iID, bEnableTrackBall) {
  287. var oPinShape = new CANNON.Cylinder(PIN_PROPERTY.radius_top, PIN_PROPERTY.radius_bottom,
  288. PIN_PROPERTY.height, PIN_PROPERTY.segments);
  289. var oPinBody = new CANNON.Body({mass: PIN_PROPERTY.mass, material: _oPinMaterial, linearDamping: PIN_PROPERTY.linearDamping,
  290. angularDamping: PIN_PROPERTY.angularDamping, userData: {type: PINS, id: iID},
  291. collisionFilterGroup: PINS,
  292. collisionFilterMask: -1,
  293. allowSleep: true,
  294. sleepTimeLimit: 1});
  295. oPinBody.addShape(oPinShape);
  296. oPinBody.position.set(oPos.x, oPos.y, oPos.z);
  297. oPinBody.addEventListener("collide", function (e) {
  298. s_oScenario.pinCollision(e);
  299. });
  300. _oWorld.addBody(oPinBody);
  301. if (SHOW_3D_RENDER) {
  302. var pinMaterial = new THREE.MeshPhongMaterial({color: 0xffffff, specular: 0x111111, shininess: 100});
  303. var oMesh = _oDemo.addVisual(oPinBody, pinMaterial);
  304. if (bEnableTrackBall && CAMERA_TEST_TRANSFORM && !CAMERA_TEST_TRACKBALL) {
  305. _oDemo.createTransformControl(oMesh, oPinBody);
  306. }
  307. }
  308. return oPinBody;
  309. };
  310. this.createWallPins = function () {
  311. var oWallShapePinsBack = new CANNON.Box(new CANNON.Vec3(WALL_PINS_SIZE.width, WALL_PINS_SIZE.depth, WALL_PINS_SIZE.height));
  312. var oShapeWallPinsSides = new CANNON.Box(new CANNON.Vec3(SIDE_WALL_PINS_SIZE.width, SIDE_WALL_PINS_SIZE.depth, SIDE_WALL_PINS_SIZE.height));
  313. var oShapeWallPinsDown = new CANNON.Box(new CANNON.Vec3(WALL_PINS_DOWN_SIZE.width, WALL_PINS_DOWN_SIZE.depth, WALL_PINS_DOWN_SIZE.height));
  314. var oShapeWallPinsForward = new CANNON.Box(new CANNON.Vec3(WALL_PINS_FORWARD_SIZE.width, WALL_PINS_FORWARD_SIZE.depth, WALL_PINS_FORWARD_SIZE.height));
  315. _oBodyWallPins = new CANNON.Body({mass: 0, material: _oWallMaterial, userData: {type: WALL}});
  316. _oBodyWallPins.addShape(oWallShapePinsBack);
  317. _oBodyWallPins.addShape(oShapeWallPinsSides, new CANNON.Vec3(WALL_PINS_SIZE.width, SIDE_WALL_PINS_SIZE.depth, 0));
  318. _oBodyWallPins.addShape(oShapeWallPinsSides, new CANNON.Vec3(-WALL_PINS_SIZE.width, SIDE_WALL_PINS_SIZE.depth, 0));
  319. _oBodyWallPins.addShape(oShapeWallPinsDown, new CANNON.Vec3(0, SIDE_WALL_PINS_SIZE.depth, -SIDE_WALL_PINS_SIZE.height));
  320. _oBodyWallPins.addShape(oShapeWallPinsForward, new CANNON.Vec3(0, WALL_PINS_DOWN_SIZE.depth * 2, -WALL_PINS_SIZE.height + WALL_PINS_FORWARD_SIZE.height));
  321. _oBodyWallPins.addShape(oShapeWallPinsDown, new CANNON.Vec3(0, SIDE_WALL_PINS_SIZE.depth, WALL_PINS_SIZE.height * 0.9));
  322. _oBodyWallPins.addEventListener("collide", function (e) {
  323. s_oScenario.wallCollision(e);
  324. });
  325. _oBodyWallPins.position.set(WALL_PINS_POSITION.x, WALL_PINS_POSITION.y, WALL_PINS_POSITION.z);
  326. _oWorld.addBody(_oBodyWallPins);
  327. if (SHOW_3D_RENDER) {
  328. var wallMaterial = new THREE.MeshPhongMaterial({color: 0x333333, specular: 0x111111, shininess: 50});
  329. _oDemo.addVisual(_oBodyWallPins, wallMaterial);
  330. }
  331. };
  332. this.createSideWallTrack = function () {
  333. var oSideWallShape = new CANNON.Box(new CANNON.Vec3(WALL_TRACK_SIZE.width, WALL_TRACK_SIZE.depth, WALL_TRACK_SIZE.height));
  334. var oRoofWallShape = new CANNON.Box(new CANNON.Vec3(ROOF_TRACK_SIZE.width, ROOF_TRACK_SIZE.depth, ROOF_TRACK_SIZE.height));
  335. _oSideWallBody = new CANNON.Body({mass: 0, material: _oWallMaterial, userData: {type: WALL_TRACK}});
  336. _oSideWallBody.addShape(oSideWallShape, new CANNON.Vec3(WALL_TRACK_SIZE.offsetX, 0, 0));
  337. _oSideWallBody.addShape(oSideWallShape, new CANNON.Vec3(-WALL_TRACK_SIZE.offsetX, 0, 0));
  338. _oSideWallBody.addShape(oRoofWallShape, new CANNON.Vec3(0, ROOF_TRACK_SIZE.offsetY, WALL_TRACK_SIZE.height * 0.85));
  339. _oSideWallBody.position.set(WALL_TRACK_POSITION.x, WALL_TRACK_POSITION.y, WALL_TRACK_POSITION.z);
  340. _oWorld.addBody(_oSideWallBody);
  341. if (SHOW_3D_RENDER && SHOW_PROXY_COLLISION) {
  342. var sideWallMaterial = new THREE.MeshPhongMaterial({color: 0xaaaaaa, specular: 0xffffff, shininess: 15});
  343. _oDemo.addVisual(_oSideWallBody, sideWallMaterial);
  344. }
  345. };
  346. this._createBallBody = function () {
  347. _oBallShape = new CANNON.Sphere(BALL_RADIUS);
  348. _oBallBody = new CANNON.Body({mass: BALL_PROPERTY.mass, material: _oBallMaterial, linearDamping: BALL_PROPERTY.linearDamping, allowSleep: false,
  349. angularDamping: BALL_PROPERTY.angularDamping, userData: {type: BALL}});
  350. var v3IniPos = new CANNON.Vec3(POSITION_BALL.x, POSITION_BALL.y, POSITION_BALL.z);
  351. _oBallBody.position.copy(v3IniPos);
  352. _oBallBody.addEventListener("collide", function (e) {
  353. s_oScenario.ballCollision(e);
  354. });
  355. _oBallBody.addShape(_oBallShape);
  356. _oWorld.add(_oBallBody);
  357. if (SHOW_3D_RENDER) {
  358. var ballMaterial = new THREE.MeshPhongMaterial({color: 0xaaaaaa, specular: 0x111111, shininess: 100});
  359. _oBallMesh = _oDemo.addVisual(_oBallBody, ballMaterial);
  360. }
  361. };
  362. this.addImpulse = function (oBody, oVec3) {
  363. var v3WorldPoint = new CANNON.Vec3(0, 0, BALL_RADIUS);
  364. var v3Impulse = new CANNON.Vec3(oVec3.x, oVec3.y, oVec3.z);
  365. oBody.applyImpulse(v3Impulse, v3WorldPoint);
  366. };
  367. this.addForce = function (oBody, oVec3) {
  368. var v3WorldPoint = new CANNON.Vec3(0, 0, 0);
  369. var v3Force = new CANNON.Vec3(oVec3.x, oVec3.y, oVec3.z);
  370. oBody.applyForce(v3Force, v3WorldPoint);
  371. };
  372. this.getBodyVelocity = function (oBody) {
  373. return oBody.velocity;
  374. };
  375. this.ballBody = function () {
  376. return _oBallBody;
  377. };
  378. this.ballMesh = function () {
  379. return _oBallMesh;
  380. };
  381. this.ballCollision = function (e) {
  382. if (e.contact.bi.userData.type === BALL && e.contact.bj.userData.type === PINS ||
  383. e.contact.bj.userData.type === BALL && e.contact.bi.userData.type === PINS) {
  384. s_oGame.setPinCollide();
  385. }
  386. };
  387. this.getCamera = function () {
  388. return _oDemo.camera();
  389. };
  390. this.floorCollision = function (e) {
  391. if (e.contact.bi.userData.type === BALL && e.contact.bj.userData.type === FLOOR ||
  392. e.contact.bj.userData.type === BALL && e.contact.bi.userData.type === FLOOR) {
  393. s_oGame.ballHitFloor();
  394. }
  395. };
  396. this.channelCollision = function (e) {
  397. if (e.contact.bi.userData.type === BALL && e.contact.bj.userData.type === CHANNEL ||
  398. e.contact.bj.userData.type === BALL && e.contact.bi.userData.type === CHANNEL) {
  399. s_oGame.gutterBall();
  400. }
  401. };
  402. this.getPinsBinder = function () {
  403. return _oPinsBinderBody;
  404. };
  405. this.getPinByID = function (iID) {
  406. return _aPin[iID];
  407. };
  408. this.setElementAngularVelocity = function (oElement, oVec3) {
  409. oElement.angularVelocity.set(oVec3.x, oVec3.y, oVec3.z);
  410. };
  411. this.setElementVelocity = function (oElement, oVec3) {
  412. var v3 = new CANNON.Vec3(oVec3.x, oVec3.y, oVec3.z);
  413. oElement.velocity = v3;
  414. };
  415. this.setElementLinearDamping = function (oElement, fValue) {
  416. oElement.linearDamping = fValue;
  417. };
  418. this.getTrackBody = function () {
  419. return _oTrackBody;
  420. };
  421. this.getTrackBodyDepth = function () {
  422. return _oBodyDepthTrack;
  423. };
  424. this.update = function () {
  425. _oWorld.step(PHYSICS_STEP);
  426. };
  427. this.resetPinsPosition = function () {
  428. for (var i = 0; i < _aPin.length; i++) {
  429. _aPin[i].position.set(PINS_POSITION[i].x, PINS_POSITION[i].y, PINS_POSITION[i].z);
  430. _aPin[i].quaternion.setFromEuler(0, 0, 0, 'XYZ');
  431. _aPin[i].angularVelocity.set(0, 0, 0);
  432. _aPin[i].velocity.set(0, 0, 0);
  433. }
  434. };
  435. this.getSideFloorPins = function (iID) {
  436. return _aSidesPinsFloor[iID];
  437. };
  438. this.pinCollision = function (e) {
  439. if (e.contact.bi.userData.type === PINS && e.contact.bj.userData.type === BALL) {
  440. s_oGame.pinSoundCollision(e.contact.bi.userData.id);
  441. } else if (e.contact.bj.userData.type === PINS && e.contact.bi.userData.type === BALL) {
  442. s_oGame.pinSoundCollision(e.contact.bj.userData.id);
  443. } else if (e.contact.bj.userData.type === PINS && e.contact.bi.userData.type === PINS) {
  444. s_oGame.twoPinsSoundCollision(e.contact.bj.userData.id, e.contact.bi.userData.id);
  445. }
  446. };
  447. this.sideWallCollision = function (e) {
  448. s_oGame.setPinDown(e.contact.bj.userData.id, true, SIDE_PINS_FLOOR);
  449. };
  450. this.sensorCollision = function (e) {
  451. e.contact.bj.sleep();
  452. if (e.contact.bj.userData.type === PINS) {
  453. s_oGame.setPinDown(e.contact.bj.userData.id, true, SIDE_PINS_FLOOR);
  454. }
  455. };
  456. this.wallCollision = function (e) {
  457. if (e.contact.bi.userData.type === BALL && e.contact.bj.userData.type === WALL ||
  458. e.contact.bj.userData.type === BALL && e.contact.bi.userData.type === WALL) {
  459. s_oGame.completeLaunch();
  460. } else if (e.contact.bj.userData.type === PINS && e.contact.bi.userData.type === WALL) {
  461. s_oGame.setPinDown(e.contact.bj.userData.id, true, WALL);
  462. }
  463. };
  464. this.destroyWorld = function () {
  465. var aBodies = _oWorld.bodies;
  466. for (var i = 0; i < aBodies.length; i++) {
  467. _oWorld.remove(aBodies[i]);
  468. }
  469. _oWorld = null;
  470. };
  471. s_oScenario = this;
  472. if (SHOW_3D_RENDER) {
  473. _oDemo.addScene("bowling", this._init);
  474. _oDemo.start();
  475. } else {
  476. this._init();
  477. }
  478. }
  479. var s_oScenario;