HeavenStudioPlus/Assets/Scripts/Games/CropStomp/CropStomp.cs

232 lines
7.6 KiB
C#
Raw Normal View History

2022-02-27 23:26:03 +00:00
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
2022-03-01 06:38:38 +00:00
using System;
2022-03-01 20:57:37 +00:00
using NaughtyBezierCurves;
2022-02-28 08:33:11 +00:00
using DG.Tweening;
2022-02-27 23:26:03 +00:00
using RhythmHeavenMania.Util;
namespace RhythmHeavenMania.Games.CropStomp
{
public class CropStomp : Minigame
{
2022-02-28 05:11:18 +00:00
const float stepDistance = 2.115f;
float scrollRate => stepDistance / (Conductor.instance.secPerBeat * 2f / Conductor.instance.musicSource.pitch);
float grassWidth;
private float newBeat = -1f; // So that marching can happen on beat 0.
private float marchStartBeat = -1f;
private float marchOffset;
private int currentMarchBeat;
private int stepCount;
2022-02-28 08:33:11 +00:00
private bool isStepping;
2022-02-28 05:11:18 +00:00
public bool isMarching => marchStartBeat != -1f && Conductor.instance.isPlaying;
2022-02-28 05:11:18 +00:00
2022-03-01 06:38:38 +00:00
[NonSerialized] public bool isFlicking;
public GameObject baseVeggie;
2022-03-03 02:50:08 +00:00
public GameObject baseMole;
2022-02-28 05:11:18 +00:00
public Animator legsAnim;
2022-03-01 06:38:38 +00:00
public Animator bodyAnim;
2022-02-28 05:11:18 +00:00
public Transform farmerTrans;
public SpriteRenderer grass;
public Transform grassTrans;
public Transform scrollingHolder;
2022-03-01 06:38:38 +00:00
public Transform veggieHolder;
2022-02-28 08:33:11 +00:00
public Farmer farmer;
2022-03-01 20:57:37 +00:00
public BezierCurve3D pickCurve;
2022-03-03 02:50:08 +00:00
public BezierCurve3D moleCurve;
2022-02-28 08:33:11 +00:00
private Tween shakeTween;
2022-02-28 05:11:18 +00:00
public static CropStomp instance;
private void Awake()
{
instance = this;
}
2022-03-03 02:50:08 +00:00
private async void Start()
2022-02-28 05:11:18 +00:00
{
// Finding grass sprite width for grass scrolling.
var grassSprite = grass.sprite;
var borderLeft = grassSprite.rect.xMin + grassSprite.border.x;
var borderRight = grassSprite.rect.xMax - grassSprite.border.z;
var borderWidthPixels = borderRight - borderLeft;
grassWidth = borderWidthPixels / grassSprite.pixelsPerUnit;
2022-03-01 06:38:38 +00:00
// Initialize vegetables.
var cond = Conductor.instance;
var entities = GameManager.instance.Beatmap.entities;
// Find the beat of the closest "start marching" event.
// If not found, default to current beat.
float startBeat = cond.songPositionInBeats;
var marchStarts = entities.FindAll(m => m.datamodel == "cropStomp/start marching");
for (int i = 0; i < marchStarts.Count; i++)
{
var sampleBeat = marchStarts[i].beat;
if (cond.songPositionInBeats <= sampleBeat + 0.25f) // 0.25-beat buffer in case the start marching event is directly next to the game switch event.
2022-03-01 06:38:38 +00:00
{
startBeat = sampleBeat;
break;
2022-03-01 06:38:38 +00:00
}
}
2022-03-03 02:50:08 +00:00
// Veggie and mole events.
2022-03-01 06:38:38 +00:00
var vegEvents = entities.FindAll(v => v.datamodel == "cropStomp/veggies");
2022-03-03 02:50:08 +00:00
var moleEvents = entities.FindAll(m => m.datamodel == "cropStomp/mole");
2022-03-01 06:38:38 +00:00
2022-03-03 02:50:08 +00:00
// Spawn veggies.
2022-03-01 06:38:38 +00:00
for (int i = 0; i < vegEvents.Count; i++)
{
var vegBeat = vegEvents[i].beat;
var vegLength = vegEvents[i].length;
// Only consider veggie events that aren't past the start point.
if (startBeat < vegBeat + vegLength)
{
int veggiesInEvent = Mathf.CeilToInt(vegLength + 1) / 2;
for (int b = 0; b < veggiesInEvent; b++)
{
var targetVeggieBeat = vegBeat + 2f * b;
if (startBeat < targetVeggieBeat)
{
2022-03-03 02:50:08 +00:00
SpawnVeggie(targetVeggieBeat, startBeat, false);
2022-03-01 06:38:38 +00:00
}
}
}
}
2022-03-03 02:50:08 +00:00
// Spawn moles.
for (int i = 0; i < moleEvents.Count; i++)
{
var moleBeat = moleEvents[i].beat;
if (startBeat < moleBeat)
{
SpawnVeggie(moleBeat, startBeat, true);
}
}
2022-02-28 05:11:18 +00:00
}
private void Update()
2022-02-27 23:26:03 +00:00
{
2022-02-28 05:11:18 +00:00
if (!isMarching)
return;
var cond = Conductor.instance;
if (cond.ReportBeat(ref newBeat, marchOffset, true))
{
currentMarchBeat += 1;
// Step.
if (currentMarchBeat % 2 != 0)
{
2022-02-28 08:33:11 +00:00
// Don't step if already stomped.
if (!isStepping)
{
stepCount += 1;
var stepAnim = (stepCount % 2 != 0 ? "StepFront" : "StepBack");
legsAnim.Play(stepAnim, 0, 0);
isStepping = true;
}
Jukebox.PlayOneShotGame("cropStomp/hmm");
2022-02-28 05:11:18 +00:00
}
// Lift.
else
{
var liftAnim = (stepCount % 2 != 0 ? "LiftBack" : "LiftFront");
legsAnim.Play(liftAnim, 0, 0);
var farmerPos = farmerTrans.localPosition;
farmerTrans.localPosition = new Vector3(farmerPos.x - stepDistance, farmerPos.y, farmerPos.z);
2022-02-28 08:33:11 +00:00
isStepping = false;
2022-02-28 05:11:18 +00:00
}
}
// Object scroll.
var scrollPos = scrollingHolder.localPosition;
var newScrollX = scrollPos.x + (scrollRate * Time.deltaTime);
scrollingHolder.localPosition = new Vector3(newScrollX, scrollPos.y, scrollPos.z);
// Grass scroll.
var grassPos = grassTrans.localPosition;
var newGrassX = grassPos.x + (scrollRate * Time.deltaTime);
newGrassX = (newGrassX % (grassWidth * 4.5f));
grassTrans.localPosition = new Vector3(newGrassX, grassPos.y, grassPos.z);
2022-02-27 23:26:03 +00:00
}
2022-03-01 06:38:38 +00:00
private void LateUpdate()
{
if (!isMarching)
return;
if (PlayerInput.PressedUp())
{
// Don't play raise animation if successfully flicked.
if (!isFlicking)
bodyAnim.Play("Raise");
}
isFlicking = false;
}
2022-02-28 05:11:18 +00:00
public void StartMarching(float beat)
2022-02-27 23:26:03 +00:00
{
2022-02-28 05:11:18 +00:00
marchStartBeat = beat;
marchOffset = (marchStartBeat % 1) * Conductor.instance.secPerBeat / Conductor.instance.musicSource.pitch;
currentMarchBeat = 0;
stepCount = 0;
2022-02-28 08:33:11 +00:00
farmer.nextStompBeat = beat;
}
public void Stomp()
{
// Don't increment step counter if autostep stepped already.
if (!isStepping)
stepCount += 1;
var stompAnim = (stepCount % 2 != 0 ? "StompFront" : "StompBack");
legsAnim.Play(stompAnim, 0, 0);
Jukebox.PlayOneShotGame("cropStomp/stomp");
if (shakeTween != null)
shakeTween.Kill(true);
var camTrans = GameCamera.instance.transform;
camTrans.localPosition = new Vector3(camTrans.localPosition.x, 0.75f, camTrans.localPosition.z);
camTrans.DOLocalMoveY(0f, 0.5f).SetEase(Ease.OutElastic, 1f);
isStepping = true;
2022-02-27 23:26:03 +00:00
}
2022-03-01 06:38:38 +00:00
2022-03-03 02:50:08 +00:00
private void SpawnVeggie(float beat, float startBeat, bool isMole)
2022-03-01 06:38:38 +00:00
{
2022-03-03 02:50:08 +00:00
var newVeggie = GameObject.Instantiate(isMole ? baseMole : baseVeggie, veggieHolder).GetComponent<Veggie>();
2022-03-01 06:38:38 +00:00
newVeggie.targetBeat = beat;
var veggieX = (beat - startBeat) * -stepDistance / 2f;
newVeggie.transform.localPosition = new Vector3(veggieX, 0f, 0f);
newVeggie.gameObject.SetActive(true);
}
2022-02-27 23:26:03 +00:00
}
}