/// <summary> /// Changes the length of the drake by modifying the last bone index /// </summary> /// <param name='newCount'> /// New bone count (superior bones will be disabled) /// </param> private void ChangeBoneCount(int newCount) { // Change index of last bone currentBoneCount = Mathf.Clamp(newCount, BONE_COUNT_MIN, bones.Length); // Update line renderer CreateBodyLine(); // Update scales int cnt = 0; for (int i = 0; i < scales.Length; ++i) { DrakeScale s = scales[i]; if (s.boneRef.index < currentBoneCount && i != 0) { if (!Helper.IsActive(scales[i].gameObject)) { Helper.SetActive(scales[i].gameObject, true); if (scales[i].glowRef != null) { Helper.SetActive(scales[i].glowRef, true); } s.Shine(); // Note : they will be updated in their Start() method //s.UpdateColorDistanceAutonomy(); } else { s.UpdateColorDistanceAutonomy(); } ++cnt; } else { Helper.SetActive(scales[i].gameObject, false); if (scales[i].glowRef != null) { Helper.SetActive(scales[i].glowRef, false); } } } currentScaleCount = cnt; // Update tail position DrakeBone lastBone = bones [currentBoneCount - 1]; tail.transform.position = lastBone.pos; }
void Start() { #region "Check parameters" targetSpeed = speedLimit.min; speed = targetSpeed; wavingPhaseSpeed = wavingPhaseSpeedMax; // Default parameters if (currentBoneCount <= BONE_COUNT_MIN) { currentBoneCount = BONE_COUNT_MIN; } #endregion #region "Create bones" // Pre-allocate the maximum number of bones bones = new DrakeBone[BONE_COUNT_MAX]; bones [0] = new DrakeBone(transform.position, 0); for (int i = 1; i < bones.Length; i++) { DrakeBone prev = bones [i - 1]; // Align as a straight line DrakeBone bone = new DrakeBone( prev.pos.x - BONE_SPACING, prev.pos.y, prev.pos.z, i); bone.angleRad = 0; // Linking bone.drakeRef = this; bone.parent = prev; prev.child = bone; bones [i] = bone; } #endregion #region "Create body line" CreateBodyLine(); #endregion #region "Create scales" // Pre-allocate the maximum number of scales // (only a subset of them will be active) scales = new DrakeScale[SCALE_COUNT_MAX]; float t_step = 1.0f / (float)scales.Length; for (int i = 0; i < scales.Length; ++i) { float t = t_step * i; // Get the bone where we will attach the scale DrakeBone bone = GetBoneFromParametric(t); // Compute a random scale ID int prefabIndex = UnityEngine.Random.Range(0, scalePrefabs.Length - 1); // Create scale GameObject scaleObject = Instantiate( scalePrefabs [prefabIndex], new Vector3(bone.pos.x, bone.pos.y, bone.pos.z), Quaternion.identity ) as GameObject; // Set its color //Material scaleMaterial = new Material (Shader.Find ("Diffuse")); //scaleMaterial.color = Color.black; MeshRenderer meshRenderer = scaleObject.GetComponent <MeshRenderer> (); meshRenderer.material = scaleMaterial; // Add scripts scaleObject.AddComponent("DrakeScale"); scaleObject.AddComponent("PainterBehavior"); // Add glow GameObject glowObj = null; if (i != 0) // because the first scale is... well, not used (See below). { glowObj = Instantiate(glowPrefab) as GameObject; } // Get scale script and init some of its variables DrakeScale scaleScript = scaleObject.GetComponent <DrakeScale> (); scaleScript.boneRef = bone; scaleScript.drakeRef = this; scaleScript.glowRef = glowObj; scaleScript.parametricPosition = t; scaleScript.indexedPosition = i; //scaleScript.materialRef = scaleMaterial; scales[i] = scaleScript; // Fix scale size const float scaleFix = 1.15f; scaleObject.transform.localScale = new Vector3(scaleFix, scaleFix, scaleFix); // Set scale as child of the drake : not useful for now } // Disable first scale because it overlaps on the head // TODO dirty code, try to do this more cleanly Helper.SetActive(scales[0].gameObject, false); #endregion #region "Create tail" DrakeBone lastBone = bones [currentBoneCount - 1]; tail = Instantiate( tailPrefab, new Vector3(lastBone.pos.x, lastBone.pos.y, lastBone.pos.z), Quaternion.identity ) as GameObject; // Set tail mesh color Material tailMaterial = new Material(Shader.Find("Diffuse")); tailMaterial.color = Color.black; tail.GetComponent <MeshRenderer>().material = tailMaterial; #endregion ChangeBoneCount(currentBoneCount); startBoneCount = currentBoneCount; //startScaleCount = currentScaleCount; if (Settings.trailerMode) { ChangeBoneCount(BONE_COUNT_MAX); } }
void Update() { if (!Settings.onTablet) { // This is just for debug. It enlarges the dragon (for free) if (Input.GetKeyDown(KeyCode.Space)) { ChangeBoneCount(BONE_COUNT_MAX); } } #region "Head update" #region "Head speed" // Gravity : // The drake has more difficulty to go up, // and is helped by gravity when going down /*float gravityModifier = Vector3.Dot(Vector3.down, transform.right); * if(gravityModifier > 0) * { * targetSpeed += gravityModifier * drakeGravity * Time.deltaTime; * }*/ // Speed addition with drake ondulations float wavingSpeedAddition = wavingToSpeedAcceleration * Mathf.Cos(wavingPhase) * speedLimit.Mid * Time.deltaTime; if (wavingSpeedAddition > 0) { targetSpeed += wavingSpeedAddition; } // Speed reduction by air friction targetSpeed -= linearSpeedReduction * Time.deltaTime; targetSpeed -= quadraticSpeedReduction * targetSpeed * targetSpeed * Time.deltaTime; bool diving = false; // Effects of the sea if (Level.Get.IsWater(transform.position.x, transform.position.y)) { // Speed is slowing // TODO maybe put this in friction code? // if (!lastFrameUnderwater) { if (transform.right.y < 0) { OnSeaDive(); diving = true; } lastFrameUnderwater = true; } } else { if (lastFrameUnderwater) { if (transform.right.y > 0) { OnSeaSurface(); } lastFrameUnderwater = false; } } #endregion #region "Head rotation and waving" // Update phase if (wavingPhaseSpeed < wavingPhaseSpeedMax) { wavingPhaseSpeed += 2f * Time.deltaTime; } wavingPhase += wavingPhaseSpeed * Time.deltaTime; // Sine waving if (periodicSineDeviation != 0) { headRotationDeg += periodicSineDeviation * Mathf.Sin(wavingPhase); } // Noise waving if (randomDeviation != 0) { if (grabbedByHornets) { headRotationDeg += UnityEngine.Random.Range(-GRAB_ROTATION_RANDOM, GRAB_ROTATION_RANDOM); } else { headRotationDeg += randomDeviation * (Mathf.PerlinNoise(wavingPhase, 0) - 0.5f); } } #endregion #region "Head final application" // Make sure we don't go out of authorized speed targetSpeed = speedLimit.Clamp(targetSpeed); // Compute instant speed //speed = (targetSpeed - speed) * acceleration * Time.deltaTime; speed = Mathf.Lerp(speed, targetSpeed, acceleration * Time.deltaTime); if (diving) { speed *= seaCoef; targetSpeed = 0f; } speed = speedLimit.Clamp(speed); // Update head rotation from target angle lastFrameHeadRotationDeg = headRotationDeg; // memorize last rotation headRotationDeg = Mathf.LerpAngle( headRotationDeg, // Current targetHeadRotationDegNorm, // Target // The faster it flies, the faster it turns rotationAbility.Lerp(speedLimit.GetT(speed)) * Time.deltaTime ); // Rotate and move forward transform.rotation = Quaternion.Euler(0f, 0f, headRotationDeg); transform.position += speed * transform.right * Time.deltaTime; #endregion #region "Paint splash" // Note from gamers point-of-view: // doing zig-zags shouldn't work because the angular speed // slightly crosses 0, and then resets splashTriggerTime. // The only way is to keep a constant angular speed, so make circles. if (Mathf.Abs(AngularSpeed) >= SPLASH_TRIGGER_ANGSPEED_DEG) { if (Time.time - splashTriggerTime >= SPLASH_TRIGGER_DELAY_S && !HasMoonPaint && !Level.Get.IsWater(transform.position.x, transform.position.y)) { DoPaintSplash(); splashTriggerTime = Time.time; if (!Settings.trailerMode) { CommonSounds.Instance.playSplash(); //michele } } } else { splashTriggerTime = Time.time; } #endregion #endregion #region "Body update" // The body must follow the head. bones [0].pos = transform.position; // Slightly offset body start (Kandinsky's head is transluscent) bones [0].pos.x -= transform.right.x; bones [0].pos.y -= transform.right.y; // Update core line for (uint i = 1; i < bones.Length; ++i) { bones [i].Update(); } // Send positions to the line renderer for (int i = 0; i < currentBoneCount; ++i) { lineRenderer.SetPosition(i, bones[i].pos); } #endregion #region "Tail update" DrakeBone lastBone = bones [currentBoneCount - 1]; tail.transform.position = lastBone.pos; tail.transform.rotation = Quaternion.Euler(90f, 0f, 0f); tail.transform.RotateAround(Vector3.forward, lastBone.angleRad + Mathf.PI); #endregion // Debug // Displays the barycenter of the dragon /*if(Settings.debugMode) * { * Vector3 b = GetBarycenter(); * TmpDebug.Instance.transform.position = b; * // Debug.DrawLine( * // new Vector3(b.x-3, b.y-3, transform.position.z), * // new Vector3(b.x-3, b.y-3, transform.position.z), Color.red, 0.5f); * }*/ }