Insanely huge initial commit

This commit is contained in:
2026-02-21 16:40:15 -08:00
parent 208d626100
commit f74c547a13
33825 changed files with 5213498 additions and 0 deletions

View File

@@ -0,0 +1,244 @@
using System;
using System.Collections;
using System.Collections.Generic;
using MoreMountains.Feedbacks;
using MoreMountains.Tools;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace MoreMountains.Feel
{
/// <summary>
/// A class used to handle Feel's Snake demo's snake "head", the part controlled by the player
/// </summary>
public class Snake : MonoBehaviour
{
[Header("Movement")]
/// the snake's movement speed
public float Speed = 5f;
/// the speed multiplier to apply at most times
public float NormalSpeedMultiplier = 1f;
/// the rate at which speed should vary
public float SpeedChangeRate = 0.2f;
/// the current direction of the snake
public Vector3 Direction = Vector2.right;
[Header("Boost")]
/// the speed multiplier to apply to the speed when boosting
public float BoostMultiplier = 2f;
/// the duration of the boost, in seconds
public float BoostDuration = 2f;
[Header("BodyParts")]
/// the prefab to use for body parts
public SnakeBodyPart BodyPartPrefab;
/// the offset to apply between two parts
public int BodyPartsOffset = 7;
/// the maximum amount of body parts for this snake
public int MaxAmountOfBodyParts = 10;
/// the minimum duration, in seconds, between 2 allowed parts losses
public float MinTimeBetweenLostParts = 2f;
[Header("Bindings")]
/// a Text component on which to display our current score
public Text PointsCounter;
[Header("Feedbacks")]
/// a feedback to play when the snake turns
public MMFeedbacks TurnFeedback;
/// a feedback to play when the snake teleports to the other side of the screen
public MMFeedbacks TeleportFeedback;
/// a feedback to play when teleporting once
public MMFeedbacks TeleportOnceFeedback;
/// a feedback to play when eating snake food
public MMFeedbacks EatFeedback;
/// a feedback to play when losing a body part
public MMFeedbacks LoseFeedback;
[Header("Debug")]
[MMReadOnly]
public int SnakePoints = 0;
[MMReadOnly]
public float _speed;
[MMReadOnly]
public float _speedMultiplier;
[MMReadOnly]
public float _lastFoodEatenAt = -100f;
protected Vector3 _newPosition;
protected MMPositionRecorder _recorder;
public List<SnakeBodyPart> _snakeBodyParts;
protected float _lastLostPart = 0f;
/// <summary>
/// On Awake, we initialize our snake's points, speed, position recorder, and body parts container
/// </summary>
protected void Awake()
{
_speed = Speed;
SnakePoints = 0;
_recorder = this.gameObject.GetComponent<MMPositionRecorder>();
PointsCounter.text = "0";
_snakeBodyParts = new List<SnakeBodyPart>();
}
/// <summary>
/// Every frame, we check for input and move our snake's head
/// </summary>
protected virtual void Update()
{
HandleInput();
HandleMovement();
}
/// <summary>
/// Every frame, looks for turn input
/// </summary>
protected virtual void HandleInput()
{
if (FeelDemosInputHelper.CheckMainActionInputPressedThisFrame())
{
Turn();
}
}
/// <summary>
/// Every frame, moves the snake's head's position
/// </summary>
protected virtual void HandleMovement()
{
_speedMultiplier = (Time.time - _lastFoodEatenAt < BoostDuration) ? BoostMultiplier : NormalSpeedMultiplier;
_speed = MMMaths.Lerp(_speed, Speed * _speedMultiplier, SpeedChangeRate, Time.deltaTime);
_newPosition = (_speed * Time.deltaTime * Direction);
this.transform.position += _newPosition;
}
/// <summary>
/// Called when turning, rotates the snake's head, changes its direction, plays a feedback
/// </summary>
public virtual void Turn()
{
TurnFeedback?.PlayFeedbacks();
Direction = MMMaths.RotateVector2(Direction, 90f);
this.transform.Rotate(new Vector3(0f,0f,90f));
}
/// <summary>
/// Called by the snake head's MMViewportEdgeTeleporter, defines what happens when the snake is teleported to the other side of the screen
/// </summary>
public virtual void Teleport()
{
StartCoroutine(TeleportCo());
}
/// <summary>
/// A coroutine used to teleport the snake to the other side of the screen
/// </summary>
/// <returns></returns>
protected virtual IEnumerator TeleportCo()
{
TeleportFeedback?.PlayFeedbacks();
TeleportOnceFeedback?.PlayFeedbacks();
yield return MMCoroutine.WaitForFrames(BodyPartsOffset);
int total = _snakeBodyParts.Count;
float feedbacksIntensity = 0f;
float part = 1 / (float)total;
for (int i = 0; i < total; i++)
{
yield return MMCoroutine.WaitForFrames(BodyPartsOffset/2);
feedbacksIntensity = 1 - i * part;
TeleportFeedback?.PlayFeedbacks(this.transform.position, feedbacksIntensity);
}
}
/// <summary>
/// Called when eating food, triggers visual effects, increases points, plays a feedback
/// </summary>
public virtual void Eat()
{
EatEffect();
EatFeedback?.PlayFeedbacks();
SnakePoints++;
PointsCounter.text = SnakePoints.ToString();
StartCoroutine(EatCo());
}
/// <summary>
/// A coroutine used to go through every snake body part and trigger its Eat MMFeedbacks
/// </summary>
protected virtual IEnumerator EatCo()
{
int total = _snakeBodyParts.Count;
float feedbacksIntensity = 0f;
float part = 1 / (float)total;
for (int i = 0; i < total; i++)
{
if (i >= _snakeBodyParts.Count)
{
yield break;
}
yield return MMCoroutine.WaitForFrames(BodyPartsOffset/2);
feedbacksIntensity = 1 - i * part;
if (i == total - 1)
{
if ((i < MaxAmountOfBodyParts - 1) && (_snakeBodyParts.Count > i))
{
if (_snakeBodyParts[i] != null)
{
_snakeBodyParts[i].New();
}
}
}
else
{
_snakeBodyParts[i].Eat(feedbacksIntensity);
}
}
}
/// <summary>
/// When eating food, we instantiate a new body part unless we've reached our limit
/// </summary>
public virtual void EatEffect()
{
_lastFoodEatenAt = Time.time;
if (SnakePoints < MaxAmountOfBodyParts - 1)
{
SnakeBodyPart part = Instantiate(BodyPartPrefab);
SceneManager.MoveGameObjectToScene(part.gameObject, this.gameObject.scene);
part.transform.position = this.transform.position;
part.TargetRecorder = _recorder;
part.Offset = ((SnakePoints) * BodyPartsOffset) + BodyPartsOffset + 1;
part.Index = _snakeBodyParts.Count;
part.name = "SnakeBodyPart_" + part.Index;
_snakeBodyParts.Add(part);
}
}
/// <summary>
/// When we lose a body part, we play a feedback, destroy the last part, lose points, and update our points display
/// </summary>
/// <param name="part"></param>
public virtual void Lose(SnakeBodyPart part)
{
if (Time.time - _lastLostPart < MinTimeBetweenLostParts)
{
return;
}
_lastLostPart = Time.time;
LoseFeedback?.PlayFeedbacks(part.transform.position);
Destroy(_snakeBodyParts[_snakeBodyParts.Count-1].gameObject);
_snakeBodyParts.RemoveAt(_snakeBodyParts.Count-1);
SnakePoints--;
PointsCounter.text = SnakePoints.ToString();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3f1b94c5b0e53534094b6c13350a5d2d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,91 @@
using System;
using System.Collections;
using System.Collections.Generic;
using MoreMountains.Feedbacks;
using MoreMountains.Tools;
using UnityEngine;
namespace MoreMountains.Feel
{
/// <summary>
/// A class used to handle Feel's Snake demo's snake bodyparts
/// </summary>
public class SnakeBodyPart : MonoBehaviour
{
/// a position recorder this body part will look at to know where to go to
public MMPositionRecorder TargetRecorder;
/// a feedback to play when food gets eaten
public MMFeedbacks EatFeedback;
/// a feedback to play when this part appears
public MMFeedbacks NewFeedback;
public int Offset = 20;
public int Index = 0;
protected Snake _snake;
protected BoxCollider2D _collider2D;
/// <summary>
/// On awake we store our collider and enable it after a delay
/// </summary>
protected virtual void Awake()
{
_collider2D = this.gameObject.MMGetComponentNoAlloc<BoxCollider2D>();
StartCoroutine(ActivateCollider());
}
/// <summary>
/// Activates this part's collider
/// </summary>
/// <returns></returns>
protected virtual IEnumerator ActivateCollider()
{
yield return MMCoroutine.WaitFor(1f);
_collider2D.enabled = true;
}
/// <summary>
/// On update, we move to the recorded position of our predecessor
/// </summary>
protected void Update()
{
this.transform.position = TargetRecorder.Positions[Offset];
}
/// <summary>
/// Called when the snake eats a new food
/// </summary>
/// <param name="intensity"></param>
public virtual void Eat(float intensity)
{
EatFeedback?.PlayFeedbacks(this.transform.position, intensity);
}
/// <summary>
/// Called when instantiating a new body part
/// </summary>
public virtual void New()
{
NewFeedback?.Initialization();
NewFeedback?.PlayFeedbacks();
}
/// <summary>
/// If we connect with the snake's head, we lose a part
/// </summary>
/// <param name="other"></param>
protected void OnTriggerEnter2D(Collider2D other)
{
if (Index == 0)
{
return;
}
_snake = other.GetComponent<Snake>();
if (_snake != null)
{
_snake.Lose(this);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b83ebdb48c79df04381830c0d5dc54a2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections;
using System.Collections.Generic;
using MoreMountains.Feedbacks;
using MoreMountains.Tools;
using UnityEngine;
namespace MoreMountains.Feel
{
/// <summary>
/// This class handles Feel's Snake demo's food objects, that the snake has to eat to score points
/// </summary>
public class SnakeFood : MonoBehaviour
{
/// a duration (in seconds) during which the food is inactive before moving it to another position
public float OffDelay = 1f;
/// the food's visual representation
public GameObject Model;
/// a feedback to play when food gets eaten
public MMFeedbacks EatFeedback;
/// a feedback to play when food appears
public MMFeedbacks AppearFeedback;
/// the food spawner
public SnakeFoodSpawner Spawner { get; set; }
protected Snake _snake;
/// <summary>
/// When this food gets eaten, we play its eat feedback, and start moving it somewhere else in the scene
/// </summary>
/// <param name="other"></param>
protected void OnTriggerEnter2D(Collider2D other)
{
_snake = other.GetComponent<Snake>();
if (_snake != null)
{
_snake.Eat();
EatFeedback?.PlayFeedbacks();
StartCoroutine(MoveFood());
}
}
/// <summary>
/// Moves the food to another spot
/// </summary>
/// <returns></returns>
protected virtual IEnumerator MoveFood()
{
Model.SetActive(false);
yield return MMCoroutine.WaitFor(OffDelay);
Model.SetActive(true);
this.transform.position = Spawner.DetermineSpawnPosition();
AppearFeedback?.PlayFeedbacks();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 22853891040a0ec409c2ba44a96285d8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,55 @@
using System.Collections;
using System.Collections.Generic;
using MoreMountains.Tools;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace MoreMountains.Feel
{
/// <summary>
/// A simple class used to spawn snake food in Feel's Snake demo scene
/// </summary>
public class SnakeFoodSpawner : MonoBehaviour
{
/// the food prefab to spawn
public SnakeFood SnakeFoodPrefab;
/// the maximum amount of food in the scene
public int AmountOfFood = 3;
/// the minimum coordinates to spawn at (in viewport units)
public Vector2 MinRandom = new Vector2(0.1f, 0.1f);
/// the maximum coordinates to spawn at (in viewport units)
public Vector2 MaxRandom = new Vector2(0.9f, 0.9f);
protected List<SnakeFood> Foods;
protected Camera _mainCamera;
/// <summary>
/// On start, instantiates food
/// </summary>
protected virtual void Start()
{
_mainCamera = Camera.main;
Foods = new List<SnakeFood>();
for (int i = 0; i < AmountOfFood; i++)
{
SnakeFood food = Instantiate(SnakeFoodPrefab);
SceneManager.MoveGameObjectToScene(food.gameObject, this.gameObject.scene);
food.transform.position = DetermineSpawnPosition();
food.Spawner = this;
Foods.Add(food);
}
}
/// <summary>
/// Determines a valid position at which to spawn food
/// </summary>
/// <returns></returns>
public virtual Vector3 DetermineSpawnPosition()
{
Vector3 newPosition = MMMaths.RandomVector2(MinRandom, MaxRandom);
newPosition.z = 10f;
newPosition = _mainCamera.ViewportToWorldPoint(newPosition);
return newPosition;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f0eb40a74b537b2469752ad2107a03fc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: