Skip to content

Instantly share code, notes, and snippets.

@kurtdekker
Created March 13, 2022 20:19
Show Gist options
  • Save kurtdekker/97920f90e31f66c4c60626011cd2014b to your computer and use it in GitHub Desktop.
Save kurtdekker/97920f90e31f66c4c60626011cd2014b to your computer and use it in GitHub Desktop.
Angry Birds, Silver: Looping Legend code for Unity3D
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