-
-
Save kwalkerxxi/bdf924928d4f70a8673a105bbde5fcfe to your computer and use it in GitHub Desktop.
Angry Birds, Silver: Looping Legend code for Unity3D
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
// kurtdekker | |
// A looping downward attack like Angry Birds, Silver: Looping Legend | |
// | |
// To use: | |
// - put this on your Rigidbody2D object | |
// - send it flying | |
// - set Trigger property true to initiate loop | |
// | |
// NOTE: this works for both left/right travel, but it is up to you | |
// to choose graphics that look correct traveling to the left. | |
// | |
// See full package at: https://forum.unity.com/threads/silver-like-movement.1251579 | |
// | |
public class SilverLooper : MonoBehaviour | |
{ | |
[Header( "Input: set this true to start (or call Trigger())")] | |
public bool Trigger; | |
[Header( "Radius of the loop.")] | |
public float CircleRadius = 1.0f; | |
[Header( "Optionally match entry to downward attack.")] | |
public bool MatchEntryToDownwardAttack; | |
// means we are started in the loop | |
bool initiated; | |
// means we have completed the loop | |
bool finishedLooping; | |
float originalSpeed; | |
float positionOnCircle; | |
float finalPositionOnCircle; | |
float rotationalRate; | |
float distanceBeforeTurning; | |
Rigidbody2D rb2d; | |
void Start() | |
{ | |
rb2d = GetComponent<Rigidbody2D>(); | |
} | |
public void TriggerLoop() | |
{ | |
Trigger = true; | |
} | |
void Update() | |
{ | |
if (!initiated) | |
{ | |
if (Trigger) | |
{ | |
initiated = true; | |
// observe our velocity now | |
Vector3 originalVelocity = rb2d.velocity; | |
// compute our initial speed | |
originalSpeed = originalVelocity.magnitude; | |
// We need to turn angles fast enough to do 360 degrees | |
// in the circumference distance of 2 * pi * radius | |
rotationalRate = (originalSpeed * 360) / (Mathf.PI * 2 * CircleRadius); | |
// this is just for clockwise vs counter clockwise | |
if (originalVelocity.x < 0) | |
{ | |
rotationalRate *= -1; | |
} | |
// find out what part of an imaginary circle we would | |
// be on while traveling at this angle. | |
float radians = Mathf.Atan2( -originalVelocity.x, originalVelocity.y); | |
// this will track our pointing as we go around | |
positionOnCircle = radians * Mathf.Rad2Deg; | |
// we're gonna be going down for final attack | |
finalPositionOnCircle = -180; | |
// make sure we get to our final position | |
if (rotationalRate > 0) | |
{ | |
while( finalPositionOnCircle < positionOnCircle) | |
{ | |
finalPositionOnCircle += 360; | |
} | |
} | |
if (rotationalRate < 0) | |
{ | |
while( finalPositionOnCircle > positionOnCircle) | |
{ | |
finalPositionOnCircle += 360; | |
} | |
} | |
// turn off gravity... we'll take it from here | |
rb2d.gravityScale = 0.0f; | |
distanceBeforeTurning = 0.0f; | |
// OPTIONAL: help the player by continuing straight ahead briefly | |
// in order to roughly match our target down-stroke attack point | |
// on the loop | |
if (MatchEntryToDownwardAttack) | |
{ | |
float xVelocity = originalVelocity.x; | |
float yVelocity = originalVelocity.y; | |
// Only adjust it up to a certain slope | |
// Beyond this limit slope, we cap out | |
const float LimitSlope = 2.0f; | |
if (Mathf.Abs( yVelocity) > LimitSlope * Mathf.Abs( xVelocity)) | |
{ | |
yVelocity = Mathf.Abs( xVelocity) * Mathf.Sign( yVelocity) * LimitSlope; | |
} | |
float angle = Mathf.Atan( yVelocity / xVelocity); | |
float sine = Mathf.Sin( angle); | |
distanceBeforeTurning = Mathf.Abs( 1 + sine) * CircleRadius; | |
} | |
// show where we were in space when we tripped the loop | |
VisibleMarkerObject.Create( rb2d.position); | |
} | |
} | |
} | |
void FixedUpdate () | |
{ | |
if (initiated) | |
{ | |
if (!finishedLooping) | |
{ | |
if (distanceBeforeTurning > 0) | |
{ | |
distanceBeforeTurning -= originalSpeed * Time.deltaTime; | |
} | |
else | |
{ | |
positionOnCircle += rotationalRate * Time.deltaTime; | |
if (rotationalRate > 0) | |
{ | |
if (positionOnCircle > finalPositionOnCircle) | |
{ | |
positionOnCircle = finalPositionOnCircle; | |
finishedLooping = true; | |
} | |
} | |
if (rotationalRate < 0) | |
{ | |
if (positionOnCircle < finalPositionOnCircle) | |
{ | |
positionOnCircle = finalPositionOnCircle; | |
finishedLooping = true; | |
} | |
} | |
} | |
} | |
Vector3 velocity = Quaternion.Euler( 0, 0, positionOnCircle) * Vector3.up; | |
velocity *= originalSpeed; | |
rb2d.velocity = velocity; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment