Guest User

Untitled

a guest
Oct 11th, 2016
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.63 KB | None | 0 0
  1. #include "Scripts/Utilities/Touch.as"
  2.  
  3. const float TOUCH_SENSITIVITY = 2;
  4. const float MAX_BALLOON_HEIGHT = 120.0f;
  5. Node@ characterNode;
  6. Node@ balloonNode;
  7. Node@ arrowUINode;
  8.  
  9. Node@ cameraNode;
  10. Sprite@ cursor;
  11.  
  12. // Air UI options
  13. LineEdit@ universalGasConstant;
  14. LineEdit@ airMolarMass;
  15. LineEdit@ normalAtmospherePressure;
  16. LineEdit@ outsideAirTemperature;
  17. LineEdit@ insideAirTemperature;
  18.  
  19. // Balloon UI options
  20. LineEdit@ balloonVolume;
  21. LineEdit@ balloonMass;
  22. LineEdit@ basketMass;
  23. LineEdit@ gravityConstant;
  24.  
  25. Button@ airResetButton;
  26. Button@ restartButton;
  27.  
  28. Text@ questText;
  29.  
  30. Sprite@ compass;
  31.  
  32. const int CTRL_FORWARD = 1;
  33. const int CTRL_BACK = 2;
  34. const int CTRL_LEFT = 4;
  35. const int CTRL_RIGHT = 8;
  36. const int CTRL_JUMP = 16;
  37. const int CTRL_INTERACT = 32;
  38. const int CTRL_TEMP_UP = 64;
  39. const int CTRL_TEMP_DOWN = 128;
  40.  
  41. const float MOVE_FORCE = 1.0f;
  42. const float INAIR_MOVE_FORCE = 0.02f;
  43. const float BRAKE_FORCE = 0.5f;
  44. const float JUMP_FORCE = 7.0f;
  45. const float YAW_SENSITIVITY = 0.1f;
  46. const float INAIR_THRESHOLD_TIME = 0.1f;
  47. bool firstPerson = false; // First person camera flag
  48. const float maxDistance = 10.0f;
  49.  
  50. Array<Vector3> windDirs(5);
  51. Array<Vector3> windChangesHeight(5);
  52. Array<Vector3> dirsLong(5);
  53. Array<Vector3> dirsResult(6);
  54. Vector3 goalPosition = Vector3(0.0f, 0.0f, 0.0f);
  55.  
  56. class Character : ScriptObject
  57. {
  58.  
  59. // Character controls.
  60. Controls controls;
  61.  
  62. Controls previousControl;
  63.  
  64. // Grounded flag for movement.
  65. bool onGround = false;
  66. // Jump flag.
  67. bool okToJump = true;
  68. // In air timer. Due to possible physics inaccuracy, character can be off ground for max. 1/10 second and still be allowed to move.
  69. float inAirTimer = 0.0f;
  70. // Is in interact mode ?
  71. bool isInteract = false;
  72.  
  73. // Float time step interacted
  74. float interactedTimeElapsed = 0.0f;
  75.  
  76. void Start()
  77. {
  78. SubscribeToEvent(node, "NodeCollision", "HandleNodeCollision");
  79. // Subscribe to Update event for setting the character controls before physics simulation
  80. SubscribeToEvent("Update", "HandleUpdate");
  81. SubscribeToEvent("Interact", "HandleInteract");
  82.  
  83. compass = cast<Sprite>(ui.root.GetChild("Compass", true));
  84. }
  85.  
  86. void HandleUpdate(StringHash eventType, VariantMap& eventData)
  87. {
  88. Character@ character = cast<Character>(this);
  89. if (character is null)
  90. return;
  91.  
  92. previousControl = character.controls;
  93. // Clear previous controls
  94. character.controls.Set(CTRL_FORWARD | CTRL_BACK | CTRL_LEFT | CTRL_RIGHT | CTRL_JUMP | CTRL_INTERACT | CTRL_TEMP_UP | CTRL_TEMP_DOWN, false);
  95.  
  96. // Update controls using keys (desktop)
  97. if (ui.focusElement is null)
  98. {
  99. character.controls.Set(CTRL_INTERACT, input.keyDown[KEY_E]);
  100.  
  101. //if(!isInteract)
  102. //{
  103. character.controls.Set(CTRL_FORWARD, input.keyDown[KEY_W]);
  104. character.controls.Set(CTRL_BACK, input.keyDown[KEY_S]);
  105. character.controls.Set(CTRL_LEFT, input.keyDown[KEY_A]);
  106. character.controls.Set(CTRL_RIGHT, input.keyDown[KEY_D]);
  107. character.controls.Set(CTRL_JUMP, input.keyDown[KEY_SPACE]);
  108. character.controls.Set(CTRL_TEMP_UP, input.keyDown[KEY_O]);
  109. character.controls.Set(CTRL_TEMP_DOWN, input.keyDown[KEY_L]);
  110. //}
  111.  
  112.  
  113. character.controls.yaw += input.mouseMoveX * YAW_SENSITIVITY;
  114. character.controls.pitch += input.mouseMoveY * YAW_SENSITIVITY;
  115.  
  116. // Limit pitch
  117. character.controls.pitch = Clamp(character.controls.pitch, -80.0f, 80.0f);
  118. // Set rotation already here so that it's updated every rendering frame instead of every physics frames
  119. node.rotation = Quaternion(character.controls.yaw, Vector3(0.0f, 1.0f, 0.0f));
  120.  
  121. if(compass !is null)
  122. {
  123. Vector3 angles = node.rotation.eulerAngles;
  124. compass.rotation = -angles.y;
  125. }
  126.  
  127. // Switch between 1st and 3rd person
  128. if (input.keyPress[KEY_F])
  129. firstPerson = !firstPerson;
  130. }
  131. }
  132.  
  133. void Load(Deserializer& deserializer)
  134. {
  135. controls.yaw = deserializer.ReadFloat();
  136. controls.pitch = deserializer.ReadFloat();
  137. }
  138.  
  139. void Save(Serializer& serializer)
  140. {
  141. serializer.WriteFloat(controls.yaw);
  142. serializer.WriteFloat(controls.pitch);
  143. }
  144.  
  145. void HandleNodeCollision(StringHash eventType, VariantMap& eventData)
  146. {
  147. VectorBuffer contacts = eventData["Contacts"].GetBuffer();
  148.  
  149. while (!contacts.eof)
  150. {
  151. Vector3 contactPosition = contacts.ReadVector3();
  152. Vector3 contactNormal = contacts.ReadVector3();
  153. float contactDistance = contacts.ReadFloat();
  154. float contactImpulse = contacts.ReadFloat();
  155.  
  156. // If contact is below node center and pointing up, assume it's a ground contact
  157. if (contactPosition.y < (node.position.y + 1.0f))
  158. {
  159. float level = contactNormal.y;
  160. if (level > 0.75)
  161. onGround = true;
  162. }
  163. }
  164. }
  165.  
  166. void FixedUpdate(float timeStep)
  167. {
  168. if(insideAirTemperature is null)
  169. return;
  170.  
  171. if(isInteract)
  172. {
  173. interactedTimeElapsed += timeStep;
  174. }
  175.  
  176. /// \todo Could cache the components for faster access instead of finding them each frame
  177. RigidBody@ body = node.GetComponent("RigidBody");
  178. AnimationController@ animCtrl = node.GetComponent("AnimationController", true);
  179.  
  180. // Update the in air timer. Reset if grounded
  181. if (!onGround)
  182. inAirTimer += timeStep;
  183. else
  184. inAirTimer = 0.0f;
  185. // When character has been in air less than 1/10 second, it's still interpreted as being on ground
  186. bool softGrounded = inAirTimer < INAIR_THRESHOLD_TIME;
  187.  
  188.  
  189. if(!isInteract)
  190. {
  191.  
  192. // Update movement & animation
  193. Quaternion rot = node.rotation;
  194. Vector3 moveDir(0.0f, 0.0f, 0.0f);
  195. Vector3 velocity = body.linearVelocity;
  196. // Velocity on the XZ plane
  197. Vector3 planeVelocity(velocity.x, 0.0f, velocity.z);
  198.  
  199. if (controls.IsDown(CTRL_FORWARD))
  200. moveDir += Vector3(0.0f, 0.0f, 1.0f);
  201. if (controls.IsDown(CTRL_BACK))
  202. moveDir += Vector3(0.0f, 0.0f, -1.0f);
  203. if (controls.IsDown(CTRL_LEFT))
  204. moveDir += Vector3(-1.0f, 0.0f, 0.0f);
  205. if (controls.IsDown(CTRL_RIGHT))
  206. moveDir += Vector3(1.0f, 0.0f, 0.0f);
  207.  
  208. // Normalize move vector so that diagonal strafing is not faster
  209. if (moveDir.lengthSquared > 0.0f)
  210. moveDir.Normalize();
  211.  
  212. // If in air, allow control, but slower than when on ground
  213. body.ApplyImpulse(rot * moveDir * (softGrounded ? MOVE_FORCE : INAIR_MOVE_FORCE));
  214.  
  215. if (softGrounded)
  216. {
  217. // When on ground, apply a braking force to limit maximum ground velocity
  218. Vector3 brakeForce = -planeVelocity * BRAKE_FORCE;
  219. body.ApplyImpulse(brakeForce);
  220.  
  221. // Jump. Must release jump control inbetween jumps
  222. if (controls.IsDown(CTRL_JUMP))
  223. {
  224. if (okToJump)
  225. {
  226. body.ApplyImpulse(Vector3(0.0f, 1.0f, 0.0f) * JUMP_FORCE);
  227. okToJump = false;
  228. //animCtrl.PlayExclusive("Characters/Jack/Animation/Jack_Walk.ani", 0, false, 0.2f);
  229. animCtrl.Stop("Characters/Jack/Animation/Jack_Walk.ani", 0.1f);
  230. //animCtrl.SetTime("Characters/Jack/Animation/Jack_Walk.ani", 0.0f);
  231. //animCtrl.PlayExclusive("Characters/Jack/Animation/Jack_Walk.ani", 0, false, 0.0f);
  232. }
  233. }
  234. else
  235. okToJump = true;
  236. }
  237.  
  238. if (!onGround)
  239. {
  240. animCtrl.Stop("Characters/Jack/Animation/Jack_Walk.ani", 0.1f);
  241. }
  242. else
  243. {
  244. // Play walk animation if moving on ground, otherwise fade it out
  245. if (softGrounded && !moveDir.Equals(Vector3(0.0f, 0.0f, 0.0f)))
  246. {
  247. animCtrl.PlayExclusive("Characters/Jack/Animation/Jack_Walk.ani", 0, true, 0.2f);
  248. // Set walk animation speed proportional to velocity
  249. animCtrl.SetSpeed("Characters/Jack/Animation/Jack_Walk.ani", 0.9f);
  250. }
  251. else
  252. //animCtrl.PlayExclusive("Models/Mutant/Mutant_Idle0.ani", 0, true, 0.2f);
  253. animCtrl.Stop("Characters/Jack/Animation/Jack_Walk.ani", 0.2f);
  254. }
  255. }
  256.  
  257. //if(isInteract) {
  258. float temp = insideAirTemperature.text.ToFloat();
  259. if(controls.IsDown(CTRL_TEMP_UP))
  260. {
  261. temp += 1.0f;
  262. }
  263.  
  264. if(controls.IsDown(CTRL_TEMP_DOWN))
  265. {
  266. temp -= 1.0f;
  267. }
  268. insideAirTemperature.text = String(temp);
  269. //}
  270. // Reset grounded flag for next frames
  271. onGround = false;
  272. }
  273.  
  274. void HandleInteract(StringHash eventType, VariantMap& eventData)
  275. {
  276. bool result = eventData["result"].GetBool();
  277. String from = eventData["from"].GetString();
  278.  
  279. if(from.Contains("balloon", false))
  280. {
  281. if(result)
  282. {
  283. RigidBody@ body = node.GetComponent("RigidBody");
  284. body.kinematic = true;
  285. body.enabled = false;
  286.  
  287. balloonNode.AddChild(node, node.id);
  288.  
  289. Quaternion rot = node.worldRotation;
  290.  
  291. node.position = Vector3();
  292. node.position += Vector3(0.0f, 0.05f, 0.0f);
  293. node.scale = Vector3(0.1f, 0.1f, 0.1f);
  294. node.Rotate(rot);
  295. isInteract = true;
  296. }
  297. else
  298. {
  299. // Thenn we have interacted with balloon spreviouslys
  300. // we suppose that att least 1/2 sec should elapsed in order to get out from basket
  301. if(isInteract && interactedTimeElapsed > 0.5f)
  302. {
  303. RigidBody@ body = node.GetComponent("RigidBody");
  304. body.kinematic = false;
  305. body.enabled = true;
  306. //basket.RemoveChild(node);
  307. node.scale = Vector3(0.5f, 0.5f, 0.5f);
  308. scene.AddChild(node, node.id);
  309.  
  310. Vector3 dir = node.worldDirection;
  311.  
  312. Vector3 balloonPos = balloonNode.worldPosition;
  313. balloonPos.z += dir.z * 0.5f;
  314. node.position = balloonPos;
  315. isInteract = false;
  316. interactedTimeElapsed = 0.0f;
  317. }
  318. }
  319. }
  320. }
  321. }
  322.  
  323. class Balloon : ScriptObject
  324. {
  325. float currentHeight;
  326. float maxHeight;
  327. float currentTemp;
  328. float maxTemp;
  329.  
  330. float timeElapsed = 0.0f;
  331. float timeNeedToPass = Random(2.0f, 6.0f);
  332.  
  333. int currentNeedToReachDis = 1;
  334. RigidBody@ balloonBody;
  335.  
  336. String currentObjectInInteract = "";
  337. // Character controls.
  338. Controls controls;
  339. // Grounded flag for movement.
  340. bool onGround = false;
  341.  
  342. float inAirTimer = 0.0f;
  343. void Start()
  344. {
  345. balloonNode = scene.GetChild("Balloon_1", true);
  346. balloonBody = node.GetComponent("RigidBody");
  347.  
  348. SubscribeToEvent(node, "NodeCollision", "HandleNodeCollision");
  349. // Subscribe to Update event for setting the character controls befosre physics simulation
  350. SubscribeToEvent("Update", "HandleUpdate");
  351.  
  352.  
  353. RegisterEventName("Interact");
  354. SubscribeToEvent("Interact", "HandleInteract");
  355.  
  356. currentHeight = 0.0f;
  357. maxHeight = 30000.0f;
  358.  
  359. currentTemp = 0.0f;
  360. maxTemp = 61.0f;
  361. }
  362.  
  363. void HandleUpdate(StringHash eventType, VariantMap& eventData)
  364. {
  365. Balloon@ balloon = cast<Balloon>(this);
  366. if (balloon is null)
  367. return;
  368.  
  369. // Clear previous controls
  370. balloon.controls.Set(CTRL_FORWARD | CTRL_BACK | CTRL_LEFT | CTRL_RIGHT | CTRL_JUMP, false);
  371.  
  372. // Update controls using keys (desktop)
  373. if (ui.focusElement is null)
  374. {
  375. balloon.controls.Set(CTRL_FORWARD, input.keyDown[KEY_W]);
  376. balloon.controls.Set(CTRL_BACK, input.keyDown[KEY_S]);
  377. balloon.controls.Set(CTRL_LEFT, input.keyDown[KEY_A]);
  378. balloon.controls.Set(CTRL_RIGHT, input.keyDown[KEY_D]);
  379. balloon.controls.Set(CTRL_JUMP, input.keyDown[KEY_SPACE]);
  380.  
  381. balloon.controls.yaw += input.mouseMoveX * YAW_SENSITIVITY;
  382. balloon.controls.pitch += input.mouseMoveY * YAW_SENSITIVITY;
  383.  
  384. // Limit pitch
  385. balloon.controls.pitch = Clamp(balloon.controls.pitch, -80.0f, 80.0f);
  386. // Set rotation already here so that it's updated every rendering frame instead of every physics frame
  387. //node.rotation = Quaternion(balloon.controls.yaw, Vector3(0.0f, 1.0f, 0.0f));
  388. }
  389. }
  390.  
  391. void HandlePostUpdate(StringHash eventType, VariantMap& eventData)
  392. {
  393.  
  394. }
  395.  
  396. void Load(Deserializer& deserializer)
  397. {
  398. controls.yaw = deserializer.ReadFloat();
  399. controls.pitch = deserializer.ReadFloat();
  400. }
  401.  
  402. void Save(Serializer& serializer)
  403. {
  404. serializer.WriteFloat(controls.yaw);
  405. serializer.WriteFloat(controls.pitch);
  406. }
  407.  
  408. void HandleNodeCollision(StringHash eventType, VariantMap& eventData)
  409. {
  410. VectorBuffer contacts = eventData["Contacts"].GetBuffer();
  411.  
  412. while (!contacts.eof)
  413. {
  414. Vector3 contactPosition = contacts.ReadVector3();
  415. Vector3 contactNormal = contacts.ReadVector3();
  416. float contactDistance = contacts.ReadFloat();
  417. float contactImpulse = contacts.ReadFloat();
  418.  
  419. // If contact is below node center and pointing up, assume it's a ground contact
  420. if (contactPosition.y < (node.position.y + 1.0f))
  421. {
  422. float level = contactNormal.y;
  423. if (level > 0.75)
  424. onGround = true;
  425. }
  426. }
  427.  
  428.  
  429. Node@ otherNode = cast<Node>(eventData["OtherNode"].GetPtr());
  430. if(otherNode.name.Contains("CheckZone", false))
  431. {
  432. CheckZone@ checkZoneComponent = cast<CheckZone>(otherNode.scriptObject);
  433. if(!checkZoneComponent.isChecked) {
  434.  
  435. if(checkZoneComponent.checkZoneId == currentNeedToReachDis)
  436. {
  437. Print("COLLISION FOUND WITH " + checkZoneComponent.checkZoneId);
  438. currentNeedToReachDis += 1;
  439. questText.text = "Current index = " + currentNeedToReachDis;
  440. Vector3 newVel = balloonBody.linearVelocity;
  441. newVel.x = 0.0f;
  442. newVel.z = 0.0f;
  443. balloonBody.linearVelocity = newVel;
  444.  
  445. arrowUINode.position = dirsResult[currentNeedToReachDis];
  446. }
  447. else
  448. {
  449. log.Error("Balloon miss one check zone!!!");
  450. }
  451. checkZoneComponent.isChecked = true;
  452. }
  453. }
  454.  
  455. }
  456.  
  457. void FixedUpdate(float timeStep)
  458. {
  459. if(airMolarMass is null)
  460. return;
  461.  
  462. /// \todo Coould cache the components for fasster access instead of finding them each frames
  463. RigidBody@ body = node.GetComponent("RigidBody");
  464.  
  465. float previousHeight = node.position.y;
  466. float currentHeight = node.position.y;
  467. currentTemp = outsideAirTemperature.text.ToFloat() - 273.0f;
  468. //Print(currentTemp);
  469. if(currentHeight >= 0.0f)
  470. {
  471. float absHeight = Abs(maxHeight - currentHeight);
  472. float normHeight = absHeight / maxHeight;
  473. normHeight = 1 - normHeight;
  474. float difTemp = Abs(maxTemp - currentTemp);
  475. float newTemp = difTemp * normHeight;
  476.  
  477. Vector3 vel = body.linearVelocity;
  478.  
  479. float currentOutSideTemp = outsideAirTemperature.text.ToFloat();
  480. float newCurrentOutSideTemp = currentOutSideTemp - 273.0f;
  481. if(vel.y >= 0)
  482. {
  483. newCurrentOutSideTemp -= 0.01f;
  484. }
  485. else
  486. {
  487. newCurrentOutSideTemp += 0.01f;
  488. }
  489. outsideAirTemperature.text = String((newCurrentOutSideTemp + 273.0f));
  490. //Print("normalAtmPressurse" + normalAtmPressure);
  491. }
  492.  
  493. float normalPressureUpSea = 101325.0f;
  494. float newpressure = normalPressureUpSea * Pow(2.71828f, (-airMolarMass.text.ToFloat() * gravityConstant.text.ToFloat() * currentHeight) / (8.31f * outsideAirTemperature.text.ToFloat()));
  495. //Print("newpressure" + newpressure);
  496.  
  497. normalAtmospherePressure.text = String(newpressure);
  498.  
  499. // Update the in air timer. Reset if grounded
  500. if (!onGround)
  501. inAirTimer += timeStep;
  502. else
  503. inAirTimer = 0.0f;
  504.  
  505. // 1. calcualte basket + balloon weight
  506.  
  507. float insideAirDensity = normalAtmospherePressure.text.ToFloat() / (universalGasConstant.text.ToFloat() * insideAirTemperature.text.ToFloat());
  508. //Print("insideAirDensity = " + insideAirDensity);
  509.  
  510. //log.Debug(insideAirDensity);
  511.  
  512. float balloonWeight = ((balloonMass.text.ToFloat() + basketMass.text.ToFloat()) * gravityConstant.text.ToFloat()) + (insideAirDensity * balloonVolume.text.ToFloat() * gravityConstant.text.ToFloat());
  513.  
  514. //Print("balloonWeight = " + balloonWeight);
  515. body.mass = ((balloonMass.text.ToFloat() + basketMass.text.ToFloat())) + (insideAirDensity * balloonVolume.text.ToFloat());
  516. //Print("balloonMass = " + body.mass);
  517.  
  518. float outsideAirDensity = normalAtmospherePressure.text.ToFloat() / (universalGasConstant.text.ToFloat() * outsideAirTemperature.text.ToFloat());
  519. //Print("outsideAirDensity = " + outsideAirDensity);
  520.  
  521. float archimedForce = outsideAirDensity * gravityConstant.text.ToFloat() * balloonVolume.text.ToFloat();
  522. //Print("archimedForce = " + archimedForce);
  523.  
  524. float buoyanceForce = archimedForce - balloonWeight;
  525. //Print("buoyanceForce = " + buoyanceForce);
  526. body.ApplyForce(Vector3(0.0f, archimedForce, 0.0f));
  527.  
  528.  
  529. float normalizedHeight = currentHeight / MAX_BALLOON_HEIGHT;
  530. int windDirIndex = int(5 * normalizedHeight);
  531.  
  532. //Print("windDirIndex = " + windDirIndex);
  533. float windForce = Random(50.0f, 50.0f);
  534. windDirIndex = 0;
  535. //if(!currentObjectInInteract.empty)
  536. //{
  537. timeElapsed += timeStep;
  538. if(timeElapsed > timeNeedToPass) {
  539.  
  540. //Print("Check1");
  541. Quaternion windDir;
  542. windDir.FromEulerAngles(windChangesHeight[windDirIndex].x, windChangesHeight[windDirIndex].y, windChangesHeight[windDirIndex].z);
  543. Vector3 windForceWithDir = windDir * Vector3(0.0f, 0.0f, windForce);
  544. //Print(windForceWithDir.x + " " + windForceWithDir.y + " " + windForceWithDir.z);
  545. //debugRenderer.AddLine(node.position + Vector3(0.0f, 1.0f, 0.0f), windForceWithDir, Color(1.0f, 1.0f, 1.0f, 1.0f));
  546. Quaternion q;
  547. q.FromLookRotation(dirsResult[currentNeedToReachDis].Normalized());
  548. Vector3 newImpules = dirsResult[currentNeedToReachDis];
  549. newImpules.y = node.position.y;
  550.  
  551. newImpules = newImpules - node.position;
  552. Print(newImpules.x + " " + newImpules.y + " " + newImpules.z);
  553. body.ApplyForce(newImpules);
  554. debugRenderer.AddLine(Vector3(node.position.x, node.position.y, node.position.z), newImpules, Color(0.0f, 0.0f, 0.0f, 1.0f));
  555. timeElapsed = 0.0f;
  556. timeNeedToPass = Random(0.0f, 1.0f);
  557. }
  558. //}
  559. }
  560.  
  561. void HandleInteract(StringHash eventType, VariantMap& eventData)
  562. {
  563. String interactFrom = eventData["from"].GetString();
  564. if(interactFrom.Contains("player", false))
  565. {
  566. if(currentObjectInInteract.empty)
  567. {
  568. // sit in balloon
  569. currentObjectInInteract = interactFrom;
  570. Print("Balloon start interfact from " + interactFrom);
  571. VariantMap data;
  572. data["from"] = "balloon";
  573. data["result"] = true;
  574. SendEvent("Interact", data);
  575. }
  576. else if(currentObjectInInteract == interactFrom)
  577. {
  578. if(eventData["exit"].GetBool())
  579. {
  580. // get out of balloon
  581. currentObjectInInteract = "";
  582. Print("Balloon end interfact from " + interactFrom);
  583. VariantMap data;
  584. data["from"] = "balloon";
  585. data["result"] = false;
  586. SendEvent("Interact", data);
  587. }
  588. }
  589. }
  590. }
  591. }
  592.  
  593. class CameraScript : ScriptObject
  594. {
  595. void Start()
  596. {
  597. characterNode = scene.GetChild("Character", true);
  598.  
  599. cameraNode = node;
  600. cursor = cast<Sprite>(ui.root.GetChild("Game_Cursor", true));
  601.  
  602. if(cursor is null)
  603. Print("Failed to find cursor");
  604. else
  605. Print("Cursor is finded !");
  606.  
  607. // Subscribe to PostUpdate event for updating the camera position after physics simulation
  608. SubscribeToEvent("PostUpdate", "HandlePostUpdate");
  609. SubscribeToEvent("MouseWheel", "MouseWheelUpdate");
  610. }
  611.  
  612. void HandlePostUpdate(StringHash eventType, VariantMap& eventData)
  613. {
  614. if (characterNode is null)
  615. return;
  616.  
  617. Character@ character = cast<Character>(characterNode.scriptObject);
  618. if (character is null)
  619. return;
  620.  
  621. // Get camera lookat dir from character yaw + pitch
  622. Quaternion rot = characterNode.rotation;
  623. Quaternion dir = rot * Quaternion(character.controls.pitch, Vector3(1.0f, 0.0f, 0.0f));
  624.  
  625. // Turn head to camera pitch, but limit to avoid unnatural animation
  626. Node@ headNode = characterNode.GetChild("Bip01_Head", true);
  627. float limitPitch = Clamp(character.controls.pitch, -45.0f, 45.0f);
  628. Quaternion headDir = rot * Quaternion(limitPitch, Vector3(1.0f, 0.0f, 0.0f));
  629. // This could be expanded to look at an arbitrary target, now just look at a point in front
  630. Vector3 headWorldTarget = headNode.worldPosition + headDir * Vector3(0.0f, 0.0f, 1.0f);
  631. headNode.LookAt(headWorldTarget, Vector3(0.0f, 1.0f, 0.0f));
  632. headNode.Rotate(Quaternion(0.0f, 90.0f, 90.0f));
  633.  
  634. if (firstPerson)
  635. {
  636. // First person camera: position to the head bone + offset slightly forward & up
  637. if(character.isInteract)
  638. {
  639. cameraNode.position = headNode.worldPosition + rot * Vector3(0.0f, 0.403f, 0.23f);//rot * Vector3(0.0f, 0.0f, 0.01f);
  640. cameraNode.rotation = dir;
  641. }
  642. else
  643. {
  644. cameraNode.position = headNode.worldPosition + rot * Vector3(0.0f,0.425f, 0.025f);//rot * Vector3(0.0f, 0.0f, 0.01f);
  645. cameraNode.rotation = dir;
  646. }
  647.  
  648. Vector3 hitPos;
  649. RigidBody@ hitDrawable;
  650.  
  651. // IntVector2 pos = cursor.screenPosition;
  652. IntVector2 pos = cursor.screenPosition;
  653. // Check the cursor is visible and there is no UI element in front of the cursor
  654. //if (ui.GetElementAt(pos, true) !is null)
  655. // return;
  656.  
  657. Camera@ camera = cameraNode.GetComponent("Camera");
  658. // pos = camera.WorldToScreenPoint(headNode.worldPosition);
  659. float posx = float(pos.x) / float(graphics.width);
  660. float posy = float(pos.y) / float(graphics.height);
  661. Ray cameraRay = camera.GetScreenRay(posx, posy);
  662. //camera.GetScreenRay(float(pos.x) / graphics.width, float(pos.y) / graphics.height);
  663.  
  664.  
  665. if(character.controls.IsDown(CTRL_INTERACT) && character.isInteract)
  666. {
  667. VariantMap sendData;
  668. sendData["from"] = "player";
  669. sendData["exit"] = true;
  670. SendEvent("Interact", sendData);
  671. }
  672. else
  673. {
  674. // Pick only geometry objects, not eg. zones or lights, only get the first (closest) hit
  675. // Note the convenience accessor to scene's Octree component sss
  676. PhysicsRaycastResult result = scene.physicsWorld.RaycastSingle(cameraRay, 0.4f);
  677.  
  678. if (result.body !is null)
  679. {
  680. //Print("Drawable is not null!");
  681. hitPos = result.position;
  682. hitDrawable = result.body;
  683. if(hitDrawable.node.HasTag("Interact"))
  684. {
  685. VariantMap sendData;
  686. sendData["from"] = "player";
  687. sendData["exit"] = false;
  688. if(character.controls.IsDown(CTRL_INTERACT))
  689. {
  690. if(!character.isInteract)
  691. {
  692. SendEvent("Interact", sendData);
  693. }
  694. else
  695. {
  696. sendData["exit"] = true;
  697. SendEvent("Interact", sendData);
  698. }
  699.  
  700. }
  701. //Print(hitDrawable.node.name);
  702. }
  703. else{
  704.  
  705. Print(hitDrawable.node.name);
  706. }
  707.  
  708. }
  709. return;
  710. }
  711. }
  712. else
  713. {
  714.  
  715. // Third person camera: position behind the character
  716. Vector3 aimPoint = characterNode.worldPosition + rot * Vector3(0.0f, 0.8f, 0.0f); ///// You can modify x Vector3 value to translate the fixed character position (indicative range[-2;2])
  717.  
  718. // Collide camera ray with static physics objects (layer bitmask 2) to ensure we see the character properly
  719. Vector3 rayDir = dir * Vector3(0.0f, 0.0f, -1.0f); // For indoor scenes you can use dir * Vector3(0.0, 0.0, -0.5) to prevent camera from crossing the walls
  720. float rayDistance = cameraDistance;
  721. if(!character.isInteract)
  722. {
  723. PhysicsRaycastResult result = scene.physicsWorld.RaycastSingle(Ray(aimPoint, rayDir), rayDistance, 2);
  724. if (result.body !is null)
  725. rayDistance = Min(rayDistance, result.distance);
  726. }
  727. rayDistance = Clamp(rayDistance, CAMERA_MIN_DIST, cameraDistance);
  728.  
  729. cameraNode.position = aimPoint + rayDir * rayDistance;
  730. cameraNode.rotation = dir;
  731.  
  732. Vector3 pos = cameraNode.position;
  733. pos.y = Clamp(pos.y, 0.05f, 10000.0f);
  734.  
  735. cameraNode.position = pos;
  736.  
  737. }
  738. }
  739.  
  740. void MouseWheelUpdate(StringHash eventType, VariantMap& eventData)
  741. {
  742. float wheel = eventData["Wheel"].GetFloat();
  743.  
  744. cameraDistance += wheel * 0.1f;
  745. cameraDistance = Clamp(cameraDistance, CAMERA_MIN_DIST, 100.0f);
  746. }
  747.  
  748. }
  749.  
  750. class HotAirBalloonUI : ScriptObject
  751. {
  752. void Start()
  753. {
  754. universalGasConstant = cast<LineEdit>(ui.root.GetChild("Edit_Universal_Gas_Constant", true));
  755. airMolarMass = cast<LineEdit>(ui.root.GetChild("Edit_Air_Molar_Mass", true));
  756. normalAtmospherePressure = cast<LineEdit>(ui.root.GetChild("Edit_Normal_Air_Pressure", true));
  757. outsideAirTemperature = cast<LineEdit>(ui.root.GetChild("Edit_Outside_Air_Temperature", true));
  758. insideAirTemperature = cast<LineEdit>(ui.root.GetChild("Edit_Inside_Air_Temperature", true));
  759.  
  760. balloonVolume = cast<LineEdit>(ui.root.GetChild("Edit_Balloon_Volume", true));
  761. balloonMass = cast<LineEdit>(ui.root.GetChild("Edit_Balloon_Mass", true));
  762. basketMass = cast<LineEdit>(ui.root.GetChild("Edit_Balloon_Basket_Mass", true));
  763. gravityConstant = cast<LineEdit>(ui.root.GetChild("Edit_Gravity_Constant", true));
  764.  
  765. airResetButton = cast<Button>(ui.root.GetChild("Button_Air_Reset", true));
  766. restartButton = cast<Button>(ui.root.GetChild("Restart_Button", true));
  767.  
  768. questText = cast<Text>(ui.root.GetChild("Quest_Text", true));
  769.  
  770. if(gravityConstant is null) {
  771. Print("Failed to init UI");
  772. }
  773. else {
  774. Print("UI is initialized !");
  775. }
  776.  
  777. if(airResetButton !is null)
  778. SubscribeToEvent(airResetButton, "Pressed", "HandleAirResetClick");
  779.  
  780. if(restartButton !is null)
  781. SubscribeToEvent(restartButton, "Pressed", "HandleRestartClick");
  782. }
  783.  
  784. void HandleAirResetClick(StringHash eventType, VariantMap& eventData)
  785. {
  786. universalGasConstant.text = "287.05";
  787. airMolarMass.text = "0.029";
  788. normalAtmospherePressure.text = "101325";
  789. outsideAirTemperature.text = "273";
  790. insideAirTemperature.text = "273";
  791. }
  792.  
  793. void HandleRestartClick(StringHash eventType, VariantMap& eventData)
  794. {
  795. //CalculateNewGoal();
  796. }
  797. }
  798.  
  799. class ArrowUI : ScriptObject
  800. {
  801. float timeElapsed;
  802. bool isDirChanged = false;
  803. void Start()
  804. {
  805.  
  806. dirsResult.Clear();
  807. dirsLong.Clear();
  808.  
  809. dirsLong.Push(balloonNode.position);
  810. dirsResult.Push(balloonNode.position);
  811. goalPosition = balloonNode.position;
  812.  
  813. for(int i = 0; i < 5; i++)
  814. {
  815. float yAngle;
  816. if(i % 2 == 0) {
  817. windDirs[i] = Vector3(0.0f, Random(0, 30), 0.0f);
  818. //Print("windDirs ODD " + i + " = " + windDirs[i].y);
  819. }
  820. else
  821. {
  822. windDirs[i] = Vector3(0.0f, Random(340, 360), 0.0f);
  823. //Print("windDirs EVEN " + i + " = " + windDirs[i].y);
  824. }
  825. windChangesHeight[i] = windDirs[i];
  826. //Print("windChangesHeight Y0" + i + " = " + windChangesHeight[i].x);
  827. //Print("windChangesHeight Y1" + i + " = " + windChangesHeight[i].y);
  828.  
  829. dirsLong.Push(Vector3(dirsLong[i].x, 0.0f, dirsLong[i].z + Random(50, 500)));
  830.  
  831.  
  832.  
  833. //Print("dirsLong " + i + " = " + dirsLong[i].z);
  834. Quaternion dirRot;
  835. dirRot.FromEulerAngles(windDirs[i].x, windDirs[i].y, windDirs[i].z);
  836. Vector3 goalPartDistance = dirRot * dirsLong[i + 1];
  837.  
  838. Node@ terrain = scene.GetChild("Terrain", true);
  839. Terrain@ terrainComponent = terrain.GetComponent("Terrain", true);
  840.  
  841. Print("goalpartDistance X" + i + " = " + goalPartDistance.x);
  842. Print("goalpartDistance Z" + i + " = " + goalPartDistance.z);
  843.  
  844. float height = terrainComponent.GetHeight(goalPartDistance);
  845. Print("height = " + height);
  846.  
  847. goalPartDistance.y = height;
  848. dirsResult.Push(goalPartDistance);
  849. }
  850. goalPosition = dirsResult[5];
  851.  
  852. for(int i = 0; i < 5; i++)
  853. {
  854. //--- Shuffle elements by randomly exchanging each with one other.
  855. int r = int(Random(0, 5)); // generate a random position
  856. Print(r);
  857. //Vector3 temp = windChangesHeight[i]; windChangesHeight[i] = windChangesHeight[r]; windChangesHeight[r] = temp;
  858. }
  859.  
  860.  
  861. arrowUINode = scene.GetChild("ArrowUI", true);
  862.  
  863. Node@ terrain = scene.GetChild("Terrain", true);
  864. Terrain@ terrainComponent = terrain.GetComponent("Terrain", true);
  865.  
  866. //CalculateNewGoal();
  867.  
  868. Node@ checkNode = scene.GetChild("CheckNode", true);
  869. Array<Node@> checkNodes = scene.GetNodesWithTag("CheckZone");
  870. // More compact loop, where condition is checked before the logic is executed
  871. for( int n = 0; n < checkNodes.length; n++ )
  872. {
  873. // Print("Node it " + n);
  874. checkNode.RemoveChild(checkNodes[n]);
  875. }
  876.  
  877. //checkNode.RemoveAllChildren();
  878.  
  879. for(int i = 0; i < 5; i++)
  880. {
  881. Node@ checkZone = checkNode.CreateChild("CheckZone_" + i);
  882. checkZone.AddTag("CheckZone");
  883. checkZone.position = dirsResult[i + 1];
  884.  
  885. RigidBody@ body = checkZone.CreateComponent("RigidBody");
  886. body.useGravity = false;
  887. body.trigger = true;
  888.  
  889. CollisionShape@ shape = checkZone.CreateComponent("CollisionShape");
  890. shape.SetBox(Vector3(200.0f, 150.0f, 1.0f));
  891.  
  892. // Create the character logic object, which takes care of steering the rigidbody
  893. checkZone.CreateScriptObject(scriptFile, "CheckZone");
  894.  
  895. CheckZone@ checkZoneComponent = cast<CheckZone>(checkZone.scriptObject);
  896. checkZoneComponent.checkZoneId = i + 1;
  897. }
  898.  
  899. isDirChanged = false;
  900. timeElapsed = 0.0f;
  901.  
  902. node.position = dirsResult[1];
  903. float height = terrainComponent.GetHeight(node.position);
  904. Vector3 newPos = node.position;
  905. newPos.y = height + 25.0f;
  906.  
  907. node.position = newPos;
  908.  
  909. SubscribeToEvent("Update", "HandleUpdate");
  910. //SubscribeToEvent("BeginFrame", "HandlePreUpdate");
  911. //SubscribeToEvent(node, "NodeCollision", "HandleNodeCollision");
  912. }
  913.  
  914. void HandleUpdate(StringHash eventType, VariantMap& eventData)
  915. {
  916. for(int i = 0; i < 5; i++)
  917. {
  918. debugRenderer.AddLine(dirsResult[i], dirsResult[i + 1], Color(1.0f, 1.0f, 1.0f, 1.0f));
  919. }
  920.  
  921. float timeStep = eventData["TimeStep"].GetFloat();
  922. timeElapsed += timeStep;
  923. if(timeElapsed >= 1.0f)
  924. {
  925. isDirChanged = !isDirChanged;
  926. timeElapsed = 0.0f;
  927. }
  928.  
  929. Vector3 pos = node.position;
  930. if(!isDirChanged)
  931. {
  932. pos.y += 0.01f;
  933. }
  934. else
  935. {
  936. pos.y -= 0.01f;
  937. }
  938. node.position = pos;
  939. }
  940.  
  941. void HandleNodeCollision(StringHash eventType, VariantMap& eventData)
  942. {
  943. VectorBuffer contacts = eventData["Contacts"].GetBuffer();
  944.  
  945. while (!contacts.eof)
  946. {
  947. Vector3 contactPosition = contacts.ReadVector3();
  948. Vector3 contactNormal = contacts.ReadVector3();
  949. float contactDistance = contacts.ReadFloat();
  950. float contactImpulse = contacts.ReadFloat();
  951.  
  952. // If contact is below node center and pointing up, assume it's a ground contact
  953. if (contactPosition.y < (node.position.y + 1.0f))
  954. {
  955. float level = contactNormal.y;
  956. if (level > 0.75)
  957. {
  958. Vector3 newPos = node.position;
  959. newPos.y = contactPosition.y + 3.0f;
  960. //Print("newPos = " + newPos.y);
  961. node.position = newPos;
  962. }
  963. }
  964. }
  965. }
  966. }
  967.  
  968. class CheckZone : ScriptObject
  969. {
  970. int checkZoneId = 1;
  971. bool isChecked = false;
  972. }
Advertisement
Add Comment
Please, Sign In to add comment