TO SQUASH: Fucking magnets, how do they work?
This commit is contained in:
@@ -31,17 +31,17 @@ public class BallSpawner : MonoBehaviour
|
||||
|
||||
ballQueue.Enqueue(() => SpawnBall(basicBallPrefab));
|
||||
ballQueue.Enqueue(() => SpawnBall(basicBallPrefab));
|
||||
// ballQueue.Enqueue(() => SpawnBall(basicBallPrefab));
|
||||
// ballQueue.Enqueue(() => SpawnBall(fruitBallPrefab));
|
||||
// ballQueue.Enqueue(() => SpawnBall(fruitBallPrefab));
|
||||
// ballQueue.Enqueue(() => SpawnBall(oozeBallPrefab));
|
||||
// ballQueue.Enqueue(() => SpawnBall(nuclearBallPrefab));
|
||||
// ballQueue.Enqueue(() => SpawnBall(glassBallPrefab));
|
||||
// ballQueue.Enqueue(() => SpawnBall(glassBallPrefab));
|
||||
// ballQueue.Enqueue(() => SpawnBall(glassBallPrefab));
|
||||
// ballQueue.Enqueue(() => SpawnBall(glassBallPrefab));
|
||||
// ballQueue.Enqueue(() => SpawnBall(glassBallPrefab));
|
||||
// ballQueue.Enqueue(() => SpawnBall(eyeBallPrefab));
|
||||
ballQueue.Enqueue(() => SpawnBall(basicBallPrefab));
|
||||
ballQueue.Enqueue(() => SpawnBall(fruitBallPrefab));
|
||||
ballQueue.Enqueue(() => SpawnBall(fruitBallPrefab));
|
||||
ballQueue.Enqueue(() => SpawnBall(oozeBallPrefab));
|
||||
ballQueue.Enqueue(() => SpawnBall(nuclearBallPrefab));
|
||||
ballQueue.Enqueue(() => SpawnBall(glassBallPrefab));
|
||||
ballQueue.Enqueue(() => SpawnBall(glassBallPrefab));
|
||||
ballQueue.Enqueue(() => SpawnBall(glassBallPrefab));
|
||||
ballQueue.Enqueue(() => SpawnBall(glassBallPrefab));
|
||||
ballQueue.Enqueue(() => SpawnBall(glassBallPrefab));
|
||||
ballQueue.Enqueue(() => SpawnBall(eyeBallPrefab));
|
||||
|
||||
StartCoroutine(SpawnBalls());
|
||||
}
|
||||
@@ -172,4 +172,32 @@ public class BallSpawner : MonoBehaviour
|
||||
|
||||
FixCollisions();
|
||||
}
|
||||
|
||||
public void MagnetActive(bool flipped)
|
||||
{
|
||||
foreach (var ball in balls)
|
||||
{
|
||||
if (ball == null) continue;
|
||||
|
||||
var ballScript = ball.GetComponent<BallBase>();
|
||||
if (ballScript != null)
|
||||
{
|
||||
ballScript.MagnetActive(flipped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void MagnetInactive()
|
||||
{
|
||||
foreach (var ball in balls)
|
||||
{
|
||||
if (ball == null) continue;
|
||||
|
||||
var ballScript = ball.GetComponent<BallBase>();
|
||||
if (ballScript != null)
|
||||
{
|
||||
ballScript.MagnetInactive();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,20 @@ public class BallBase : MonoBehaviour
|
||||
|
||||
protected bool affectedByMagnet = true;
|
||||
|
||||
protected bool magnetActiveLeftRight = false;
|
||||
|
||||
protected bool magnetActiveTopBottom = false;
|
||||
|
||||
protected struct MagnetBounceAxisState
|
||||
{
|
||||
public bool magnetWasActive;
|
||||
public bool bouncingToAnchor;
|
||||
public float anchor;
|
||||
public float target;
|
||||
public float bounceTimer;
|
||||
public int sideDirection;
|
||||
}
|
||||
|
||||
void OnTriggerEnter2D(Collider2D other)
|
||||
{
|
||||
if(other.gameObject.CompareTag("Bar"))
|
||||
@@ -42,4 +56,139 @@ public class BallBase : MonoBehaviour
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void MagnetActive(bool flipped)
|
||||
{
|
||||
if (flipped)
|
||||
{
|
||||
magnetActiveTopBottom = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
magnetActiveLeftRight = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void MagnetInactive()
|
||||
{
|
||||
magnetActiveTopBottom = false;
|
||||
magnetActiveLeftRight = false;
|
||||
}
|
||||
|
||||
protected float ApplyMagnetBounceAxis(
|
||||
float currentValue,
|
||||
float minBound,
|
||||
float maxBound,
|
||||
bool magnetIsActive,
|
||||
ref MagnetBounceAxisState state,
|
||||
float colliderExtent,
|
||||
float bounceDuration,
|
||||
float centerLeeway)
|
||||
{
|
||||
if (!magnetIsActive)
|
||||
{
|
||||
state.magnetWasActive = false;
|
||||
state.sideDirection = 0;
|
||||
state.bounceTimer = 0.0f;
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
float center = (minBound + maxBound) * 0.5f;
|
||||
float halfSpan = (maxBound - minBound) * 0.5f;
|
||||
float maxLeeway = Mathf.Max(0.0f, halfSpan - colliderExtent);
|
||||
float safeLeeway = Mathf.Clamp(centerLeeway, 0.0f, maxLeeway);
|
||||
float leftAnchorMax = center - safeLeeway;
|
||||
float rightAnchorMin = center + safeLeeway;
|
||||
|
||||
if (!state.magnetWasActive)
|
||||
{
|
||||
state.magnetWasActive = true;
|
||||
state.anchor = currentValue;
|
||||
state.sideDirection = state.anchor <= center ? -1 : 1;
|
||||
state.target = state.sideDirection < 0 ? minBound + colliderExtent : maxBound - colliderExtent;
|
||||
state.bouncingToAnchor = false;
|
||||
state.bounceTimer = 0.0f;
|
||||
}
|
||||
|
||||
// Keep the selected side locked while magnet is active.
|
||||
if (state.sideDirection < 0)
|
||||
{
|
||||
state.anchor = Mathf.Min(state.anchor, leftAnchorMax);
|
||||
}
|
||||
else
|
||||
{
|
||||
state.anchor = Mathf.Max(state.anchor, rightAnchorMin);
|
||||
}
|
||||
|
||||
state.bounceTimer += Time.fixedDeltaTime;
|
||||
float t = Mathf.Clamp01(state.bounceTimer / bounceDuration);
|
||||
|
||||
if (state.bouncingToAnchor)
|
||||
{
|
||||
// Mirror NukeBall ascent: ease-out from target back to anchor.
|
||||
float easedT = 1.0f - Mathf.Pow(1.0f - t, 2.0f);
|
||||
currentValue = Mathf.Lerp(state.target, state.anchor, easedT);
|
||||
|
||||
if (t >= 1.0f)
|
||||
{
|
||||
state.bouncingToAnchor = false;
|
||||
state.bounceTimer = 0.0f;
|
||||
currentValue = state.anchor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mirror NukeBall descent: ease-in from anchor down to side target.
|
||||
float easedT = t * t;
|
||||
currentValue = Mathf.Lerp(state.anchor, state.target, easedT);
|
||||
|
||||
if (t >= 1.0f)
|
||||
{
|
||||
state.bouncingToAnchor = true;
|
||||
state.bounceTimer = 0.0f;
|
||||
currentValue = state.target;
|
||||
}
|
||||
}
|
||||
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
protected bool TryCacheGameBoardBounds(out Bounds bounds)
|
||||
{
|
||||
var gameBoard = FindAnyObjectByType<GameBoard>();
|
||||
if (gameBoard != null)
|
||||
{
|
||||
return TryGetWorldBounds(gameBoard.gameObject, out bounds);
|
||||
}
|
||||
|
||||
bounds = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected static bool TryGetWorldBounds(GameObject target, out Bounds bounds)
|
||||
{
|
||||
Collider2D collider2D = target.GetComponent<Collider2D>();
|
||||
if (collider2D != null)
|
||||
{
|
||||
bounds = collider2D.bounds;
|
||||
return true;
|
||||
}
|
||||
|
||||
Renderer renderer = target.GetComponent<Renderer>();
|
||||
if (renderer != null)
|
||||
{
|
||||
bounds = renderer.bounds;
|
||||
return true;
|
||||
}
|
||||
|
||||
Collider collider3D = target.GetComponent<Collider>();
|
||||
if (collider3D != null)
|
||||
{
|
||||
bounds = collider3D.bounds;
|
||||
return true;
|
||||
}
|
||||
|
||||
bounds = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,32 @@ using UnityEngine;
|
||||
|
||||
public class BasicBall : BallBase
|
||||
{
|
||||
private Bounds boardBounds;
|
||||
|
||||
private Collider2D selfCollider;
|
||||
|
||||
private bool hasBoardBounds = false;
|
||||
|
||||
// Faster pull keeps the ball on its current board half while magnet is active.
|
||||
private float magnetBounceDuration = 0.35f;
|
||||
|
||||
// Prevents magnet bounces from reaching the board center line.
|
||||
private float magnetCenterLeeway = 0.12f;
|
||||
|
||||
private MagnetBounceAxisState xMagnetBounceState;
|
||||
|
||||
private MagnetBounceAxisState yMagnetBounceState;
|
||||
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
audioSource = GetComponent<AudioSource>();
|
||||
animator = GetComponent<Animator>();
|
||||
selfCollider = GetComponent<Collider2D>();
|
||||
speed = new Vector2(Random.Range(-0.05f, 0.05f), Random.Range(-0.05f, 0.05f));
|
||||
|
||||
hasBoardBounds = TryCacheGameBoardBounds(out boardBounds);
|
||||
|
||||
audioSource.PlayOneShot(spawnSound);
|
||||
}
|
||||
|
||||
@@ -19,6 +38,35 @@ public class BasicBall : BallBase
|
||||
|
||||
if (stateInfo.IsName("BasicBallMove")) {
|
||||
transform.Translate(speed);
|
||||
|
||||
if (affectedByMagnet && hasBoardBounds)
|
||||
{
|
||||
Vector3 currentPosition = transform.position;
|
||||
|
||||
currentPosition.x = ApplyMagnetBounceAxis(
|
||||
currentPosition.x,
|
||||
boardBounds.min.x,
|
||||
boardBounds.max.x,
|
||||
magnetActiveLeftRight,
|
||||
ref xMagnetBounceState,
|
||||
selfCollider != null ? selfCollider.bounds.extents.x : 0.0f,
|
||||
magnetBounceDuration,
|
||||
magnetCenterLeeway
|
||||
);
|
||||
|
||||
currentPosition.y = ApplyMagnetBounceAxis(
|
||||
currentPosition.y,
|
||||
boardBounds.min.y,
|
||||
boardBounds.max.y,
|
||||
magnetActiveTopBottom,
|
||||
ref yMagnetBounceState,
|
||||
selfCollider != null ? selfCollider.bounds.extents.y : 0.0f,
|
||||
magnetBounceDuration,
|
||||
magnetCenterLeeway
|
||||
);
|
||||
|
||||
transform.position = currentPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,4 +80,5 @@ public class BasicBall : BallBase
|
||||
speed = Vector2.Reflect(speed, contact.normal);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,13 +4,30 @@ public class EyeBall : BallBase
|
||||
{
|
||||
private static float reorientationAngleDegrees = 3f;
|
||||
|
||||
private Bounds boardBounds;
|
||||
|
||||
private Collider2D selfCollider;
|
||||
|
||||
private bool hasBoardBounds = false;
|
||||
|
||||
private float magnetBounceDuration = 0.35f;
|
||||
|
||||
private float magnetCenterLeeway = 0.12f;
|
||||
|
||||
private MagnetBounceAxisState xMagnetBounceState;
|
||||
|
||||
private MagnetBounceAxisState yMagnetBounceState;
|
||||
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
audioSource = GetComponent<AudioSource>();
|
||||
animator = GetComponent<Animator>();
|
||||
selfCollider = GetComponent<Collider2D>();
|
||||
speed = new Vector2(Random.Range(-0.05f, 0.05f), Random.Range(-0.05f, 0.05f));
|
||||
|
||||
hasBoardBounds = TryCacheGameBoardBounds(out boardBounds);
|
||||
|
||||
audioSource.PlayOneShot(spawnSound);
|
||||
}
|
||||
|
||||
@@ -40,6 +57,35 @@ public class EyeBall : BallBase
|
||||
|
||||
if (stateInfo.IsName("EyeBallMove")) {
|
||||
transform.Translate(speed);
|
||||
|
||||
if (affectedByMagnet && hasBoardBounds)
|
||||
{
|
||||
Vector3 currentPosition = transform.position;
|
||||
|
||||
currentPosition.x = ApplyMagnetBounceAxis(
|
||||
currentPosition.x,
|
||||
boardBounds.min.x,
|
||||
boardBounds.max.x,
|
||||
magnetActiveLeftRight,
|
||||
ref xMagnetBounceState,
|
||||
selfCollider != null ? selfCollider.bounds.extents.x : 0.0f,
|
||||
magnetBounceDuration,
|
||||
magnetCenterLeeway
|
||||
);
|
||||
|
||||
currentPosition.y = ApplyMagnetBounceAxis(
|
||||
currentPosition.y,
|
||||
boardBounds.min.y,
|
||||
boardBounds.max.y,
|
||||
magnetActiveTopBottom,
|
||||
ref yMagnetBounceState,
|
||||
selfCollider != null ? selfCollider.bounds.extents.y : 0.0f,
|
||||
magnetBounceDuration,
|
||||
magnetCenterLeeway
|
||||
);
|
||||
|
||||
transform.position = currentPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,14 +6,31 @@ public class FruitBall : BallBase
|
||||
|
||||
private float speedIncreaseTimer = 0.0f;
|
||||
|
||||
private Bounds boardBounds;
|
||||
|
||||
private Collider2D selfCollider;
|
||||
|
||||
private bool hasBoardBounds = false;
|
||||
|
||||
private float magnetBounceDuration = 0.35f;
|
||||
|
||||
private float magnetCenterLeeway = 0.12f;
|
||||
|
||||
private MagnetBounceAxisState xMagnetBounceState;
|
||||
|
||||
private MagnetBounceAxisState yMagnetBounceState;
|
||||
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
audioSource = GetComponent<AudioSource>();
|
||||
animator = GetComponent<Animator>();
|
||||
selfCollider = GetComponent<Collider2D>();
|
||||
speed = new Vector2(Mathf.Sign(Random.Range(-1f, 1f)) * 0.005f,
|
||||
Mathf.Sign(Random.Range(-1f, 1f)) * 0.005f);
|
||||
|
||||
hasBoardBounds = TryCacheGameBoardBounds(out boardBounds);
|
||||
|
||||
audioSource.PlayOneShot(spawnSound);
|
||||
}
|
||||
|
||||
@@ -24,6 +41,35 @@ public class FruitBall : BallBase
|
||||
|
||||
if (stateInfo.IsName("FruitBallMove")) {
|
||||
transform.Translate(speed * speedMultiplier);
|
||||
|
||||
if (affectedByMagnet && hasBoardBounds)
|
||||
{
|
||||
Vector3 currentPosition = transform.position;
|
||||
|
||||
currentPosition.x = ApplyMagnetBounceAxis(
|
||||
currentPosition.x,
|
||||
boardBounds.min.x,
|
||||
boardBounds.max.x,
|
||||
magnetActiveLeftRight,
|
||||
ref xMagnetBounceState,
|
||||
selfCollider != null ? selfCollider.bounds.extents.x : 0.0f,
|
||||
magnetBounceDuration,
|
||||
magnetCenterLeeway
|
||||
);
|
||||
|
||||
currentPosition.y = ApplyMagnetBounceAxis(
|
||||
currentPosition.y,
|
||||
boardBounds.min.y,
|
||||
boardBounds.max.y,
|
||||
magnetActiveTopBottom,
|
||||
ref yMagnetBounceState,
|
||||
selfCollider != null ? selfCollider.bounds.extents.y : 0.0f,
|
||||
magnetBounceDuration,
|
||||
magnetCenterLeeway
|
||||
);
|
||||
|
||||
transform.position = currentPosition;
|
||||
}
|
||||
}
|
||||
|
||||
if (speedIncreaseTimer > 0.0f)
|
||||
|
||||
@@ -15,14 +15,31 @@ public class GlassBall : BallBase
|
||||
|
||||
private SpriteRenderer spriteRenderer;
|
||||
|
||||
private Bounds boardBounds;
|
||||
|
||||
private Collider2D selfCollider;
|
||||
|
||||
private bool hasBoardBounds = false;
|
||||
|
||||
private float magnetBounceDuration = 0.35f;
|
||||
|
||||
private float magnetCenterLeeway = 0.12f;
|
||||
|
||||
private MagnetBounceAxisState xMagnetBounceState;
|
||||
|
||||
private MagnetBounceAxisState yMagnetBounceState;
|
||||
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
audioSource = GetComponent<AudioSource>();
|
||||
animator = GetComponent<Animator>();
|
||||
spriteRenderer = GetComponent<SpriteRenderer>();
|
||||
selfCollider = GetComponent<Collider2D>();
|
||||
speed = new Vector2(Random.Range(-0.05f, 0.05f), Random.Range(-0.05f, 0.05f));
|
||||
|
||||
hasBoardBounds = TryCacheGameBoardBounds(out boardBounds);
|
||||
|
||||
audioSource.PlayOneShot(spawnSound);
|
||||
}
|
||||
|
||||
@@ -41,6 +58,35 @@ public class GlassBall : BallBase
|
||||
stateInfo.IsName("GlassBallMove3"))
|
||||
{
|
||||
transform.Translate(speed);
|
||||
|
||||
if (affectedByMagnet && hasBoardBounds)
|
||||
{
|
||||
Vector3 currentPosition = transform.position;
|
||||
|
||||
currentPosition.x = ApplyMagnetBounceAxis(
|
||||
currentPosition.x,
|
||||
boardBounds.min.x,
|
||||
boardBounds.max.x,
|
||||
magnetActiveLeftRight,
|
||||
ref xMagnetBounceState,
|
||||
selfCollider != null ? selfCollider.bounds.extents.x : 0.0f,
|
||||
magnetBounceDuration,
|
||||
magnetCenterLeeway
|
||||
);
|
||||
|
||||
currentPosition.y = ApplyMagnetBounceAxis(
|
||||
currentPosition.y,
|
||||
boardBounds.min.y,
|
||||
boardBounds.max.y,
|
||||
magnetActiveTopBottom,
|
||||
ref yMagnetBounceState,
|
||||
selfCollider != null ? selfCollider.bounds.extents.y : 0.0f,
|
||||
magnetBounceDuration,
|
||||
magnetCenterLeeway
|
||||
);
|
||||
|
||||
transform.position = currentPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,20 @@ public class OozeBall : BallBase
|
||||
|
||||
private SpriteRenderer spriteRenderer;
|
||||
|
||||
private Bounds boardBounds;
|
||||
|
||||
private Collider2D selfCollider;
|
||||
|
||||
private bool hasBoardBounds = false;
|
||||
|
||||
private float magnetBounceDuration = 0.35f;
|
||||
|
||||
private float magnetCenterLeeway = 0.12f;
|
||||
|
||||
private MagnetBounceAxisState xMagnetBounceState;
|
||||
|
||||
private MagnetBounceAxisState yMagnetBounceState;
|
||||
|
||||
private float splitTimer = 10.0f;
|
||||
|
||||
private float tickTimer = 0.5f;
|
||||
@@ -23,8 +37,11 @@ public class OozeBall : BallBase
|
||||
audioSource = GetComponent<AudioSource>();
|
||||
animator = GetComponent<Animator>();
|
||||
spriteRenderer = GetComponent<SpriteRenderer>();
|
||||
selfCollider = GetComponent<Collider2D>();
|
||||
speed = new Vector2(Random.Range(-0.05f, 0.05f), Random.Range(-0.05f, 0.05f));
|
||||
|
||||
hasBoardBounds = TryCacheGameBoardBounds(out boardBounds);
|
||||
|
||||
audioSource.PlayOneShot(spawnSound);
|
||||
}
|
||||
|
||||
@@ -35,6 +52,35 @@ public class OozeBall : BallBase
|
||||
|
||||
if (stateInfo.IsName("OozeBallMove") || stateInfo.IsName("OozeBallSplit")) {
|
||||
transform.Translate(speed);
|
||||
|
||||
if (affectedByMagnet && hasBoardBounds)
|
||||
{
|
||||
Vector3 currentPosition = transform.position;
|
||||
|
||||
currentPosition.x = ApplyMagnetBounceAxis(
|
||||
currentPosition.x,
|
||||
boardBounds.min.x,
|
||||
boardBounds.max.x,
|
||||
magnetActiveLeftRight,
|
||||
ref xMagnetBounceState,
|
||||
selfCollider != null ? selfCollider.bounds.extents.x : 0.0f,
|
||||
magnetBounceDuration,
|
||||
magnetCenterLeeway
|
||||
);
|
||||
|
||||
currentPosition.y = ApplyMagnetBounceAxis(
|
||||
currentPosition.y,
|
||||
boardBounds.min.y,
|
||||
boardBounds.max.y,
|
||||
magnetActiveTopBottom,
|
||||
ref yMagnetBounceState,
|
||||
selfCollider != null ? selfCollider.bounds.extents.y : 0.0f,
|
||||
magnetBounceDuration,
|
||||
magnetCenterLeeway
|
||||
);
|
||||
|
||||
transform.position = currentPosition;
|
||||
}
|
||||
}
|
||||
|
||||
splitTimer -= Time.deltaTime;
|
||||
|
||||
@@ -64,6 +64,8 @@ public class Player : MonoBehaviour
|
||||
|
||||
public GameObject magnetBottom;
|
||||
|
||||
public BallSpawner ballSpawner;
|
||||
|
||||
private bool flipped = false;
|
||||
|
||||
private bool gameOver = false;
|
||||
@@ -233,6 +235,8 @@ public class Player : MonoBehaviour
|
||||
magnetRight.GetComponent<SpriteRenderer>().enabled = false;
|
||||
magnetTop.GetComponent<SpriteRenderer>().enabled = false;
|
||||
magnetBottom.GetComponent<SpriteRenderer>().enabled = false;
|
||||
|
||||
ballSpawner.MagnetInactive();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -393,6 +397,7 @@ public class Player : MonoBehaviour
|
||||
magnetRight.GetComponent<SpriteRenderer>().enabled = true;
|
||||
}
|
||||
|
||||
ballSpawner.MagnetActive(flipped);
|
||||
DisableMagnet();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user