add bgm playback, scrolling based on bgm time

This commit is contained in:
msk
2023-09-29 16:16:44 -07:00
parent 02b7f023fd
commit 2a6e64dbfd
6 changed files with 131 additions and 44 deletions
+46
View File
@@ -0,0 +1,46 @@
using Godot;
using Godot.Collections;
using System;
public partial class BGM : AudioStreamPlayer
{
public void LoadFromUser(string path)
{
if (!path.StartsWith("user://"))
{
GD.Print("Tried to load audio that isn't in user directory.");
return;
}
var f = FileAccess.Open(path, FileAccess.ModeFlags.Read);
if (f == null)
{
GD.PrintErr($"Unable to open {path} for loading audio! {FileAccess.GetOpenError()}");
return;
}
GD.Print("hi");
var ext = path.Split('.')[^1].ToLower();
switch (ext)
{
case "mp3":
var mp3 = new AudioStreamMP3()
{
Data = f.GetBuffer((long)f.GetLength())
};
Stream = mp3;
break;
case "wav":
case "wave":
var wav = new AudioStreamWav()
{
Data = f.GetBuffer((long)f.GetLength())
};
Stream = wav;
break;
case "ogg":
// TODO: implement
GD.PrintErr("External OGGs not supported in Godot 4.1...");
break;
}
}
}
+15
View File
@@ -0,0 +1,15 @@
using Godot;
using System;
public partial class SFX : Node
{
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process(double delta)
{
}
}
+137
View File
@@ -0,0 +1,137 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection.PortableExecutable;
using Godot;
using WacK.Configuration;
using WacK.Data.Chart;
using WacK.Data.Mer;
using WacK.Things.TunnelObjects;
namespace WacK.Scenes
{
public class PlayParameters
{
/* TODO: store song ID from internal database
public string songID;
public Difficulty diff;
*/
public string chartPath;
public string soundPath;
public PlayParameters(string chPath, string snPath)
{
chartPath = chPath;
soundPath = snPath;
GD.Print($"Chart: {chartPath}\nSound: {soundPath}");
}
}
public partial class Play : Node
{
// initialized by another scene, BEFORE loading this one!
public static PlayParameters playParams;
// TunnelObjects we can instantiate
public static PackedScene noteTouch = GD.Load<PackedScene>("res://Things/TunnelObjects/Notes/NoteTouch.tscn");
public static PackedScene noteHold = GD.Load<PackedScene>("res://Things/TunnelObjects/Notes/NoteHold.tscn");
public static PackedScene noteChain = GD.Load<PackedScene>("res://Things/TunnelObjects/Notes/NoteChain.tscn");
[ExportCategory("Audio")]
[Export]
private BGM bgmController;
[Export]
private SFX sfxController;
[ExportCategory("2D")]
[ExportSubgroup("2D Things")]
[Export]
public Control noteDisplay;
[Export]
public Control scrollDisplay;
[Export]
public Background background;
[ExportSubgroup("Out-of-bounds Viewports")]
[Export]
public Viewport mainViewport;
[Export]
public Viewport leftViewport;
[Export]
public Viewport rightViewport;
private Chart chart;
// base scroll speed, which we can apply multipliers on
public static readonly float BASE_PIXELS_PER_SECOND = 800;
public static float scrollPxPerSec
{
get
{
return BASE_PIXELS_PER_SECOND * PlaySettings.playSpeedMultiplier.Value;
}
}
public override void _Ready()
{
// so we can see objects outside of the 0-60min. region
leftViewport.World2D = mainViewport.World2D;
rightViewport.World2D = mainViewport.World2D;
// parse mer and create chart for current play
chart = new(playParams.chartPath);
RealizeChart();
// audio setup
bgmController.LoadFromUser(playParams.soundPath);
bgmController.Play();
}
/// <summary>
/// Instantiates necessary notes onto noteDisplay for the player to see.
/// </summary>
private void RealizeChart()
{
foreach (var msNote in chart.playNotes)
{
foreach (var note in msNote.Value)
{
THNotePlay nNote;
switch (note.type)
{
case NotePlayType.HoldStart:
nNote = noteHold.Instantiate<THNoteHold>();
((THNoteHold)nNote).InitHold((NoteHold)note, scrollDisplay);
break;
case NotePlayType.Touch:
nNote = noteTouch.Instantiate<THNotePlay>();
break;
case NotePlayType.Untimed:
nNote = noteChain.Instantiate<THNotePlay>();
break;
default:
continue;
}
nNote.Init(note);
var nPos = nNote.Position;
nPos.Y = msNote.Key * -scrollPxPerSec;
nNote.Position = nPos;
noteDisplay.AddChild(nNote);
}
}
}
public override void _Process(double delta)
{
double time = bgmController.GetPlaybackPosition() + AudioServer.GetTimeSinceLastMix() - AudioServer.GetOutputLatency();
var nPos = noteDisplay.Position;
nPos.Y = ((float)time * scrollPxPerSec) + 1920;
noteDisplay.Position = nPos;
scrollDisplay.Position = nPos;
}
private void OnDestroy()
{
playParams = null;
}
}
}