mirror of
https://github.com/RHeavenStudio/HeavenStudio.git
synced 2025-06-13 18:27:37 +02:00
Basketball Girls (#858)
* wip * Secretly fixed bugs in unrelated areas * wip2 * wip3 * camera * OK
This commit is contained in:
8
Assets/Scripts/Games/BasketballGirls.meta
Normal file
8
Assets/Scripts/Games/BasketballGirls.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f5754c28d2ba9441814255c52bf93e5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
104
Assets/Scripts/Games/BasketballGirls/Ball.cs
Normal file
104
Assets/Scripts/Games/BasketballGirls/Ball.cs
Normal file
@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
using HeavenStudio.Util;
|
||||
|
||||
namespace HeavenStudio.Games.Scripts_BasketballGirls
|
||||
{
|
||||
public class Ball : MonoBehaviour
|
||||
{
|
||||
public double startBeat;
|
||||
[SerializeField] private Animator ballAnim;
|
||||
|
||||
private BasketballGirls game;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
game = BasketballGirls.instance;
|
||||
ballAnim.DoScaledAnimationAsync("prepare", 0.5f);
|
||||
game.ScheduleInput(startBeat, 1, BasketballGirls.InputAction_Catch, JustCatch, MissCatch, Empty);
|
||||
}
|
||||
|
||||
void JustCatch(PlayerActionEvent caller, float state)
|
||||
{
|
||||
game.girlRightNoBopIntervals.Add(new Interval(startBeat + 1, startBeat + 2));
|
||||
|
||||
if (state <= -1f || state >= 1f)
|
||||
{
|
||||
SoundByte.PlayOneShotGame("basketballGirls/catch");
|
||||
MultiSound.Play(
|
||||
new MultiSound.Sound[] {
|
||||
new MultiSound.Sound("basketballGirls/throw", startBeat + 1.5),
|
||||
new MultiSound.Sound("basketballGirls/6", startBeat + 2),
|
||||
}
|
||||
);
|
||||
|
||||
ballAnim.DoScaledAnimationAsync("catch", 0.5f);
|
||||
game.girlLeftAnim.DoScaledAnimationAsync("pass", 0.5f);
|
||||
game.girlRightAnim.DoScaledAnimationAsync("catch", 0.5f);
|
||||
BeatAction.New(this, new List<BeatAction.Action>()
|
||||
{
|
||||
new BeatAction.Action(startBeat + 1.5, delegate {
|
||||
ballAnim.DoScaledAnimationAsync("shootBarely", 0.5f);
|
||||
game.girlRightAnim.DoScaledAnimationAsync("shoot", 0.5f);
|
||||
}),
|
||||
new BeatAction.Action(startBeat + 2, delegate {
|
||||
ballAnim.DoScaledAnimationAsync("barely", 0.5f);
|
||||
game.goalAnim.DoScaledAnimationAsync("barely", 0.5f);
|
||||
}),
|
||||
new BeatAction.Action(startBeat + 3, delegate {
|
||||
Destroy(gameObject);
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
SoundByte.PlayOneShotGame("basketballGirls/catch");
|
||||
MultiSound.Play(
|
||||
new MultiSound.Sound[] {
|
||||
new MultiSound.Sound("basketballGirls/throw", startBeat + 1.5),
|
||||
new MultiSound.Sound("basketballGirls/dunk", startBeat + 2),
|
||||
new MultiSound.Sound("basketballGirls/ok1", startBeat + 2.5),
|
||||
new MultiSound.Sound("basketballGirls/ok2", startBeat + 3),
|
||||
}
|
||||
);
|
||||
|
||||
ballAnim.DoScaledAnimationAsync("catch", 0.5f);
|
||||
if (!game.girlLeftNoBopIntervals.Any(x => x.Start == (startBeat + 1))) game.girlLeftAnim.DoScaledAnimationAsync("pass", 0.5f);
|
||||
game.girlRightAnim.DoScaledAnimationAsync("catch", 0.5f);
|
||||
BeatAction.New(this, new List<BeatAction.Action>()
|
||||
{
|
||||
new BeatAction.Action(startBeat + 1.5, delegate {
|
||||
ballAnim.DoScaledAnimationAsync("shootJust", 0.5f);
|
||||
game.girlRightAnim.DoScaledAnimationAsync("shoot", 0.5f);
|
||||
}),
|
||||
new BeatAction.Action(startBeat + 2, delegate {
|
||||
ballAnim.DoScaledAnimationAsync("just", 0.5f);
|
||||
game.goalAnim.DoScaledAnimationAsync("just", 0.5f);
|
||||
}),
|
||||
new BeatAction.Action(startBeat + 3, delegate {
|
||||
Destroy(gameObject);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
void MissCatch(PlayerActionEvent caller)
|
||||
{
|
||||
SoundByte.PlayOneShotGame("basketballGirls/" + UnityEngine.Random.Range(1,2).ToString());
|
||||
ballAnim.DoScaledAnimationAsync("hit", 0.5f);
|
||||
game.girlLeftAnim.DoScaledAnimationAsync("shock", 0.5f);
|
||||
game.girlRightAnim.DoScaledAnimationAsync("hit", 0.5f);
|
||||
game.girlRightNoBopIntervals.Add(new Interval(startBeat + 1, startBeat + 2));
|
||||
BeatAction.New(this, new List<BeatAction.Action>()
|
||||
{
|
||||
new BeatAction.Action(startBeat + 3, delegate {
|
||||
Destroy(gameObject);
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
void Empty(PlayerActionEvent caller) { }
|
||||
}
|
||||
}
|
11
Assets/Scripts/Games/BasketballGirls/Ball.cs.meta
Normal file
11
Assets/Scripts/Games/BasketballGirls/Ball.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 118bbd422c37f2a4eafcb0c2fc904392
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
272
Assets/Scripts/Games/BasketballGirls/BasketballGirls.cs
Normal file
272
Assets/Scripts/Games/BasketballGirls/BasketballGirls.cs
Normal file
@ -0,0 +1,272 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
using HeavenStudio.Util;
|
||||
using HeavenStudio.InputSystem;
|
||||
|
||||
using Jukebox;
|
||||
|
||||
namespace HeavenStudio.Games.Loaders
|
||||
{
|
||||
using static Minigames;
|
||||
public static class RvlBasketLoader
|
||||
{
|
||||
public static Minigame AddGame(EventCaller eventCaller)
|
||||
{
|
||||
return new Minigame("basketballGirls", "Basketball Girls", "ffffff", false, false, new List<GameAction>()
|
||||
{
|
||||
new("bop", "Bop")
|
||||
{
|
||||
function = delegate { var e = eventCaller.currentEntity; BasketballGirls.instance.ToggleBop(e.beat, e.length, e["toggle"], e["auto"]);},
|
||||
resizable = true,
|
||||
parameters = new()
|
||||
{
|
||||
new("toggle", true, "Bop"),
|
||||
new("auto", false, "Bop (Auto)")
|
||||
}
|
||||
},
|
||||
new GameAction("ball", "Ball")
|
||||
{
|
||||
function = delegate {var e = eventCaller.currentEntity; BasketballGirls.instance.SpawnBall(e.beat); },
|
||||
defaultLength = 2f,
|
||||
},
|
||||
new GameAction("zoom", "Zoom In/Out")
|
||||
{
|
||||
function = delegate { var e = eventCaller.currentEntity; BasketballGirls.instance.ToggleZoom(e.beat, e.length, e["ease"], e["toggle"]);},
|
||||
defaultLength = 4f,
|
||||
resizable = true,
|
||||
parameters = new List<Param>()
|
||||
{
|
||||
new Param("toggle", true, "Zoom In", "Toggle if the camera should zoom in."),
|
||||
new Param("ease", Util.EasingFunction.Ease.Linear, "Ease", "Set the easing of the action."),
|
||||
}
|
||||
},
|
||||
new GameAction("background appearance", "Background Appearance")
|
||||
{
|
||||
function = delegate {
|
||||
var e = eventCaller.currentEntity;
|
||||
BasketballGirls.instance.BackgroundColorSet(e.beat, e.length, e["colorBGStart"], e["colorBGEnd"], e["ease"]);
|
||||
},
|
||||
defaultLength = 0.5f,
|
||||
resizable = true,
|
||||
parameters = new List<Param>()
|
||||
{
|
||||
new Param("colorBGStart", new Color(1f, 0.937f, 0.224f), "Start BG Color", "Set the color at the start of the event."),
|
||||
new Param("colorBGEnd", new Color(1f, 0.937f, 0.224f), "End BG Color", "Set the color at the end of the event."),
|
||||
new Param("ease", Util.EasingFunction.Ease.Instant, "Ease", "Set the easing of the action."),
|
||||
}
|
||||
},
|
||||
},
|
||||
new List<string>() { "rvl", "normal" },
|
||||
"rvlbasket", "en",
|
||||
new List<string>() {},
|
||||
chronologicalSortKey: 105
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace HeavenStudio.Games
|
||||
{
|
||||
using Scripts_BasketballGirls;
|
||||
public class BasketballGirls : Minigame
|
||||
{
|
||||
public Transform baseBall;
|
||||
public Animator girlLeftAnim, girlRightAnim;
|
||||
[NonSerialized] public List<Interval> girlLeftNoBopIntervals = new(),
|
||||
girlRightNoBopIntervals = new();
|
||||
public Animator goalAnim;
|
||||
|
||||
public Transform[] CameraPosition;
|
||||
double cameraMoveBeat = double.MaxValue;
|
||||
double cameraMoveLength;
|
||||
Util.EasingFunction.Ease cameraMoveEase;
|
||||
bool cameraMoveIn;
|
||||
|
||||
[SerializeField] private SpriteRenderer BGPlane;
|
||||
|
||||
private ColorEase bgColorEase = new(new Color(1f, 0.937f, 0.224f));
|
||||
|
||||
public static BasketballGirls instance;
|
||||
|
||||
const int IAAltDownCat = IAMAXCAT;
|
||||
|
||||
protected static bool IA_BatonAltPress(out double dt)
|
||||
{
|
||||
return PlayerInput.GetSqueezeDown(out dt);
|
||||
}
|
||||
|
||||
public static PlayerInput.InputAction InputAction_Catch =
|
||||
new("RvlBasketCatch", new int[] { IAPressCat, IAPressCat, IAAltDownCat },
|
||||
IA_PadBasicPress, IA_TouchBasicPress, IA_BatonAltPress);
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
instance = this;
|
||||
SetupBopRegion("basketballGirls", "bop", "auto");
|
||||
HandleBops();
|
||||
}
|
||||
|
||||
public override void OnLateBeatPulse(double beat)
|
||||
{
|
||||
if (BeatIsInBopRegion(beat)) { Bop(beat);}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
var cond = Conductor.instance;
|
||||
if (cond.isPlaying && !cond.isPaused)
|
||||
{
|
||||
if (PlayerInput.GetIsAction(InputAction_Catch) && !IsExpectingInputNow(InputAction_Catch))
|
||||
{
|
||||
if (!girlRightAnim.IsPlayingAnimationNames("blank") && !girlRightNoBopIntervals.Any(x => x.Contains(cond.songPositionInBeatsAsDouble)))
|
||||
{
|
||||
SoundByte.PlayOneShotGame("basketballGirls/A");
|
||||
girlRightAnim.DoScaledAnimationAsync("blank", 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateCamera(cond.songPositionInBeatsAsDouble);
|
||||
UpdateBackgroundColor();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleBops()
|
||||
{
|
||||
List<RiqEntity> events = EventCaller.GetAllInGameManagerList("basketballGirls", new string[] { "ball" });
|
||||
|
||||
foreach (var e in events)
|
||||
{
|
||||
girlLeftNoBopIntervals.Add(new Interval(e.beat, e.beat + 2));
|
||||
}
|
||||
}
|
||||
public void ToggleBop(double beat, float length, bool bopOrNah, bool autoBop)
|
||||
{
|
||||
if (bopOrNah)
|
||||
{
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
var currentBeat = beat + i;
|
||||
BeatAction.New(instance, new List<BeatAction.Action>()
|
||||
{
|
||||
new BeatAction.Action(currentBeat, delegate { Bop(currentBeat);})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Bop(double beat)
|
||||
{
|
||||
if (!girlLeftNoBopIntervals.Any(x => x.Contains(beat)))
|
||||
{
|
||||
MultiSound.Play(
|
||||
new MultiSound.Sound[] {
|
||||
new MultiSound.Sound("basketballGirls/dribble" + UnityEngine.Random.Range(1,3).ToString(), beat),
|
||||
new MultiSound.Sound("basketballGirls/dribbleEcho" + UnityEngine.Random.Range(1,4).ToString(), beat + 0.5),
|
||||
}
|
||||
);
|
||||
girlLeftAnim.DoScaledAnimationAsync("dribble", 0.5f);
|
||||
}
|
||||
if (!girlRightNoBopIntervals.Any(x => x.Contains(beat)))
|
||||
{
|
||||
girlRightAnim.DoScaledAnimationAsync("bop", 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
public void SpawnBall(double beat)
|
||||
{
|
||||
var newBall = Instantiate(baseBall, transform).GetComponent<Ball>();
|
||||
newBall.startBeat = beat;
|
||||
|
||||
SoundByte.PlayOneShotGame("basketballGirls/voice");
|
||||
girlLeftAnim.DoScaledAnimationAsync("prepare", 0.5f);
|
||||
BeatAction.New(instance, new List<BeatAction.Action>()
|
||||
{
|
||||
new BeatAction.Action(beat, delegate {
|
||||
newBall.gameObject.SetActive(true);
|
||||
newBall.Init();
|
||||
}),
|
||||
new BeatAction.Action(beat+2, delegate {
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
public void ToggleZoom(double beat, double length, int ease, bool toggle)
|
||||
{
|
||||
cameraMoveBeat = beat;
|
||||
cameraMoveLength = length;
|
||||
cameraMoveEase = (Util.EasingFunction.Ease)ease;
|
||||
cameraMoveIn = toggle;
|
||||
}
|
||||
private void UpdateCamera(double beat)
|
||||
{
|
||||
Vector3 cameraPosition;
|
||||
|
||||
if (beat >= cameraMoveBeat)
|
||||
{
|
||||
Util.EasingFunction.Function func = Util.EasingFunction.GetEasingFunction(cameraMoveEase);
|
||||
float prog = conductor.GetPositionFromBeat(cameraMoveBeat, cameraMoveLength, true);
|
||||
prog = Mathf.Clamp01(prog);
|
||||
if (cameraMoveIn)
|
||||
{
|
||||
cameraPosition.x = func(CameraPosition[0].position.x, CameraPosition[1].position.x, prog);
|
||||
cameraPosition.y = func(CameraPosition[0].position.y, CameraPosition[1].position.y, prog);
|
||||
cameraPosition.z = func(CameraPosition[0].position.z, CameraPosition[1].position.z, prog);
|
||||
}
|
||||
else
|
||||
{
|
||||
cameraPosition.x = func(CameraPosition[1].position.x, CameraPosition[0].position.x, prog);
|
||||
cameraPosition.y = func(CameraPosition[1].position.y, CameraPosition[0].position.y, prog);
|
||||
cameraPosition.z = func(CameraPosition[1].position.z, CameraPosition[0].position.z, prog);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cameraMoveIn) cameraPosition = CameraPosition[1].position;
|
||||
else cameraPosition = CameraPosition[0].position;
|
||||
}
|
||||
|
||||
GameCamera.AdditionalPosition = cameraPosition - GameCamera.defaultPosition;
|
||||
}
|
||||
|
||||
public void BackgroundColorSet(double beat, float length, Color BGStart, Color BGEnd, int colorEaseSet)
|
||||
{
|
||||
bgColorEase = new(beat, length, BGStart, BGEnd, colorEaseSet);
|
||||
|
||||
UpdateBackgroundColor();
|
||||
}
|
||||
private void UpdateBackgroundColor()
|
||||
{
|
||||
BGPlane.color = bgColorEase.GetColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// How should Bop's on/off be managed?
|
||||
namespace HeavenStudio.Games.Scripts_BasketballGirls
|
||||
{
|
||||
public class Interval
|
||||
{
|
||||
private readonly double _start;
|
||||
private readonly double _end;
|
||||
private readonly Func<double, double, bool> _leftComparer;
|
||||
private readonly Func<double, double, bool> _rightComparer;
|
||||
|
||||
public double Start => _start;
|
||||
public double End => _end;
|
||||
|
||||
public Interval(double start, double end, bool isLeftClosed = true, bool isRightClosed = false)
|
||||
{
|
||||
_start = start;
|
||||
_end = end;
|
||||
|
||||
_leftComparer = isLeftClosed ? (value, boundary) => value >= boundary : (value, boundary) => value > boundary;
|
||||
_rightComparer = isRightClosed ? (value, boundary) => value <= boundary : (value, boundary) => value < boundary;
|
||||
}
|
||||
|
||||
public bool Contains(double value) => _leftComparer(value, _start) && _rightComparer(value, _end);
|
||||
}
|
||||
}
|
11
Assets/Scripts/Games/BasketballGirls/BasketballGirls.cs.meta
Normal file
11
Assets/Scripts/Games/BasketballGirls/BasketballGirls.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd41ea1e783b5f043b24b752b4133444
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -111,6 +111,7 @@ namespace HeavenStudio.Games
|
||||
void JustHold(PlayerActionEvent caller, float state)
|
||||
{
|
||||
var currentBeat = caller.timer + caller.startBeat;
|
||||
isJust = false;
|
||||
ScheduleInput(currentBeat, 1, InputAction_FlickRelease, JustJump, MissJump, Empty, CanJump);
|
||||
|
||||
if (state >= 1f || state <= -1f)
|
||||
@ -132,6 +133,7 @@ namespace HeavenStudio.Games
|
||||
void JustJump(PlayerActionEvent caller, float state)
|
||||
{
|
||||
var currentBeat = caller.timer + caller.startBeat;
|
||||
isJust = true;
|
||||
|
||||
if (state >= 1f || state <= -1f)
|
||||
{
|
||||
@ -147,7 +149,8 @@ namespace HeavenStudio.Games
|
||||
JumpMissAnim(caller.timer + caller.startBeat);
|
||||
}
|
||||
|
||||
bool CanJump() { return isHold && !isGone;}
|
||||
bool isJust = false; // not fundamental solution
|
||||
bool CanJump() { return isHold && !isGone || isJust;}
|
||||
|
||||
void Empty(PlayerActionEvent caller) { }
|
||||
|
||||
|
Reference in New Issue
Block a user