Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A collection of utilities for creating rhythm games in Unity, Unreal, Godot, SDL and MonoGame.

License

NotificationsYou must be signed in to change notification settings

neogeek/rhythm-game-utilities

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Caution

This package is in early development and should not be used in production.

Rhythm Game Utilities

TestsBuildNugetJoin the chat at https://discord.gg/nNtFsfd

This library is a collection of utilities for creating rhythm games like Tap Tap Revenge, Guitar Hero, and Rock Band. It is meant to be used within any game engine that supports loading C++ libraries, such as Unity, Unreal, Godot, SDL and MonoGame.

Prototype game built using these utilities.Prototype game built using these utilities.

Features

  • 🎵 Parse.chart and.midi song files
  • 🎼 Calculate position to render notes
  • 💯 Calculate hit accuracy
  • 🥁 Determine if the current time is on the beat
  • 💫 And more!

Social

Table of Contents

Platforms

This library aims to offer support for multiple platforms through a single codebase. This is highly ambitious, so if you run into an issue with your platform of choice during development, please leave a detailed bug report with as much information as possible. Also, as this library is relatively new, mobile platforms will be fully supported after all other platforms are complete.

EngineLanguagePlatformVersionTestedStable
UnityC#macOS6000.0.22f1
2022.3.50f1
2021.3.44f1
UnityC#Windows6000.0.22f1
2022.3.50f1
2021.3.44f1
UnrealC++macOS5.4.4
UnrealC++Windows5.4.4
Godot 4GDScriptmacOS4.3
Godot 4GDScriptWindows4.3
Godot 4C#macOS4.3
Godot 4C#Windows4.3
SDLC++macOS2.30.8
SDLC++Windows2.30.8--
MonoGameC#macOS3.8.2
MonoGameC#Windows3.8.2

Install

Unity

  1. Add package via git URL
    https://github.com/neogeek/rhythm-game-utilities.git?path=/UnityPackage
  2. Import the sample project (optional)
    • Check the materials to make sure they work in the version of Unity and render pipeline you selected.

Unreal

  1. Clone this repo locally (using either a tagged release or the main development branch).
  2. Add the include path to your<project>.Build.cs file.
    PublicIncludePaths.AddRange(newstring[]{"D:/git/github/rhythm-game-utilities/include"});

Godot

GDScript

Download and install the latest release fromhttps://github.com/rhythm-game-utilities/godot-plugin.

C#

Install the nuget packagecom.neogeek.rhythm-game-utilities via the CLI or from within your IDE.

dotnet add package com.neogeek.rhythm-game-utilities --version 1.0.0-alpha.4

SDL

  1. Clone this repo locally (using either a tagged release or the main development branch).
  2. Add the include path to your project.
    • VS Code:.vscode/c_cpp_properties.json
      "includePath": ["${workspaceFolder}/**","${HOME}/git/github/rhythm-game-utilities/include/**"]
  3. Add the include path to your build command.
    • g++
      g++ -std=c++17 -o build/output src/*.cpp -Isrc \    -I"${HOME}/git/github/rhythm-game-utilities/include/" \    -I/opt/homebrew/Cellar/sdl2/2.30.8/include/SDL2 -L/opt/homebrew/Cellar/sdl2/2.30.8/lib \    -lSDL2
  4. Add the include path to your CMAKECMakeLists.txt file.
    include_directories($ENV{HOME}/git/github/rhythm-game-utilities/include/)

MonoGame

Install the nuget packagecom.neogeek.rhythm-game-utilities via the CLI or from within your IDE.

dotnet add package com.neogeek.rhythm-game-utilities --version 1.0.0-alpha.4

API

Audio

Audio.ConvertSamplesToWaveform

Languages:C#

usingRhythmGameUtilities;varsamples=newfloat[_audioSource.clip.samples*_audioSource.clip.channels];_audioSource.clip.GetData(samples,0);varcolor=Color.red;vartransparentColor=newColor(0,0,0,0);varwaveform=Audio.ConvertSamplesToWaveform(samples,_texture2D.width,_texture2D.height);for(varx=0;x<waveform.Length;x+=1){for(vary=0;y<waveform[x].Length;y+=1){_texture2D.SetPixel(x,y,waveform[x][y]==1?color:transparentColor);}}_texture2D.Apply();

Common

Common.InverseLerp

Languages:C#C++GDScript

C#
usingSystem;usingRhythmGameUtilities;varvalue=Common.InverseLerp(0,10,5);Console.WriteLine(value);// 0.5
C++
#include<iostream>#include"RhythmGameUtilities/Common.hpp"usingnamespaceRhythmGameUtilities;intmain(){auto value =InverseLerp(0,10,5);    std::cout << value << std::endl;// 0.5return0;}
GDScript
extendsNodefunc_ready()->void:varvalue=rhythm_game_utilities.inverse_lerp(0,10,5)print(value)# 0.5

Common.Lerp

Languages:C#C++GDScript

C#
usingSystem;usingRhythmGameUtilities;varvalue=Common.Lerp(0,10,0.5f);Console.WriteLine(value);// 5
C++
#include<iostream>#include"RhythmGameUtilities/Common.hpp"usingnamespaceRhythmGameUtilities;intmain(){auto value =Lerp(0,10,0.5f);    std::cout << value << std::endl;// 5return0;}
GDScript
extendsNodefunc_ready()->void:varvalue=rhythm_game_utilities.lerp(0,10,0.5)print(value)# 5

Parsers

Read more about.chart files:https://github.com/TheNathannator/GuitarGame_ChartFormats/blob/main/doc/FileFormats/.chart/Core%20Infrastructure.md

Parsers.ParseLyricsFromChartSection

Languages:C#C++GDScript

C#
usingSystem;usingRhythmGameUtilities;varsections=Parsers.ParseSectionsFromChart(contents);varlyrics=Parsers.ParseLyricsFromChartSection(sections[NamedSection.Events]);Console.WriteLine(lyrics.Count);// 12
C++
#include<iostream>#include"RhythmGameUtilities/File.hpp"#include"RhythmGameUtilities/Parsers.hpp"usingnamespaceRhythmGameUtilities;intmain(){auto content =ReadStringFromFile("./song.chart");auto sections =ParseSectionsFromChart(content.c_str());auto lyrics =ParseLyricsFromChartSection(        sections.at(ToString(NamedSection::Events)));    std::cout <<size(lyrics) << std::endl;// 12return0;}
GDScript
extendsNodefunc_ready()->void:varfile=FileAccess.open("res://song.chart",FileAccess.READ)varcontent=file.get_as_text()varsections=rhythm_game_utilities.parse_sections_from_chart(content)varlyrics=rhythm_game_utilities.parse_lyrics_from_chart_section(sections["Events"])print(lyrics)

Parsers.ParseMetaDataFromChartSection

Languages:C#C++GDScript

C#
usingSystem;usingRhythmGameUtilities;varsections=Parsers.ParseSectionsFromChart(contents);varmetaData=Parsers.ParseMetaDataFromChartSection(sections[NamedSection.Song]);Console.WriteLine(metaData["Name"]);// Example SongConsole.WriteLine(metaData["Resolution"]);// 192Console.WriteLine(metaData["MusicStream"]);// Example Song.ogg
C++
#include<iostream>#include"RhythmGameUtilities/File.hpp"#include"RhythmGameUtilities/Parsers.hpp"usingnamespaceRhythmGameUtilities;intmain(){auto content =ReadStringFromFile("./song.chart");auto sections =ParseSectionsFromChart(content.c_str());auto metaData =ParseMetaDataFromChartSection(        sections.at(ToString(NamedSection::Song)));    std::cout << metaData["Name"] << std::endl;// Example Song    std::cout << metaData["Resolution"] << std::endl;// 192    std::cout << metaData["MusicStream"] << std::endl;// Example Song.oggreturn0;}
GDScript
extendsNodefunc_ready()->void:varfile=FileAccess.open("res://song.chart",FileAccess.READ)varcontent=file.get_as_text()varsections=rhythm_game_utilities.parse_sections_from_chart(content)varmeta_data=rhythm_game_utilities.parse_meta_data_from_chart_section(sections["Song"])print(meta_data)

Parsers.ParseNotesFromChartSection

Languages:C#C++GDScript

C#
usingSystem;usingRhythmGameUtilities;varsections=Parsers.ParseSectionsFromChart(contents);varnotes=Parsers.ParseNotesFromChartSection(sections[$"{Difficulty.Expert}Single"]);Console.WriteLine(notes.Length);// 8
C++
#include<iostream>#include"RhythmGameUtilities/File.hpp"#include"RhythmGameUtilities/Parsers.hpp"usingnamespaceRhythmGameUtilities;intmain(){auto content =ReadStringFromFile("./song.chart");auto sections =ParseSectionsFromChart(content.c_str());auto notes =ParseNotesFromChartSection(        sections.at(ToString(Difficulty::Expert) +"Single"));for (auto &note : notes)    {if (note.HandPosition >5)        {continue;        }        std::cout << note.Position <<"" << note.HandPosition << std::endl;    }return0;}
GDScript
extendsNodefunc_ready()->void:varfile=FileAccess.open("res://song.chart",FileAccess.READ)varcontent=file.get_as_text()varsections=rhythm_game_utilities.parse_sections_from_chart(content)varnotes=rhythm_game_utilities.parse_notes_from_chart_section(sections["ExpertSingle"])print(notes)

Parsers.ParseSectionsFromChart

Languages:C#C++GDScript

C#
usingSystem;usingRhythmGameUtilities;varsections=Parsers.ParseSectionsFromChart(contents);Console.WriteLine(sections.Count);// 4
C++
#include<iostream>#include"RhythmGameUtilities/File.hpp"#include"RhythmGameUtilities/Parsers.hpp"usingnamespaceRhythmGameUtilities;intmain(){auto content =ReadStringFromFile("./song.chart");auto sections =ParseSectionsFromChart(content.c_str());    std::cout <<size(sections) << std::endl;// 4return0;}
GDScript
extendsNodefunc_ready()->void:varfile=FileAccess.open("res://song.chart",FileAccess.READ)varcontent=file.get_as_text()varsections=rhythm_game_utilities.parse_sections_from_chart(content)print(sections)

Parsers.ParseTempoChangesFromChartSection

Languages:C#C++GDScript

C#
usingSystem;usingRhythmGameUtilities;varsections=Parsers.ParseSectionsFromChart(contents);vartempoChanges=Parsers.ParseTempoChangesFromChartSection(sections[NamedSection.SyncTrack]);Console.WriteLine(tempoChanges.Length);// 7
C++
#include<iostream>#include"RhythmGameUtilities/File.hpp"#include"RhythmGameUtilities/Parsers.hpp"usingnamespaceRhythmGameUtilities;intmain(){auto content =ReadStringFromFile("./song.chart");auto sections =ParseSectionsFromChart(content.c_str());auto tempoChanges =ParseTempoChangesFromChartSection(        sections.at(ToString(NamedSection::SyncTrack)));    std::cout <<size(tempoChanges) << std::endl;// 7return0;}
GDScript
extendsNodefunc_ready()->void:varfile=FileAccess.open("res://song.chart",FileAccess.READ)varcontent=file.get_as_text()varsections=rhythm_game_utilities.parse_sections_from_chart(content)vartempo_changes=rhythm_game_utilities.parse_tempo_changes_from_chart_section(sections["SyncTrack"])print(tempo_changes)

Parsers.ParseTimeSignatureChangesFromChartSection

Languages:C#C++GDScript

C#
usingSystem;usingRhythmGameUtilities;varsections=Parsers.ParseSectionsFromChart(contents);vartimeSignatureChanges=Parsers.ParseTimeSignatureChangesFromChartSection(sections[NamedSection.SyncTrack]);Console.WriteLine(timeSignatureChanges.Length);// 4
C++
#include<iostream>#include"RhythmGameUtilities/File.hpp"#include"RhythmGameUtilities/Parsers.hpp"usingnamespaceRhythmGameUtilities;intmain(){auto content =ReadStringFromFile("./song.chart");auto sections =ParseSectionsFromChart(content.c_str());auto timeSignatureChanges =ParseTimeSignatureChangesFromChartSection(        sections.at(ToString(NamedSection::SyncTrack)));    std::cout <<size(timeSignatureChanges) << std::endl;// 4return0;}
GDScript
extendsNodefunc_ready()->void:varfile=FileAccess.open("res://song.chart",FileAccess.READ)varcontent=file.get_as_text()varsections=rhythm_game_utilities.parse_sections_from_chart(content)vartime_signature_changes=rhythm_game_utilities.parse_time_signature_changes_from_chart_section(sections["SyncTrack"])print(time_signature_changes)

Utilities

Utilities.CalculateAccuracyRatio

Languages:C#C++GDScript

C#
usingSystem;usingRhythmGameUtilities;constintseconds=2;constintresolution=192;constintpositionDelta=50;vartempoChanges=newTempo[]{new(){Position=0,BPM=120000}};vartimeSignatureChanges=newTimeSignature[]{new(){Position=0,Numerator=4,Denominator=2}};varnote=newNote{Position=750};varcurrentPosition=Utilities.ConvertSecondsToTicks(seconds,resolution,tempoChanges,timeSignatureChanges);varvalue=Utilities.CalculateAccuracyRatio(note.Position,currentPosition,positionDelta);Console.WriteLine(value);// 0.64
C++
#include<iostream>#include"RhythmGameUtilities/Utilities.hpp"usingnamespaceRhythmGameUtilities;intmain(){constint seconds =2;constint resolution =192;constint positionDelta =50;    std::vector<Tempo> tempoChanges = {{0,120000}};    std::vector<TimeSignature> timeSignatureChanges = {{0,4}};auto note =new Note{750};auto currentPosition =ConvertSecondsToTicks(        seconds, resolution, tempoChanges, timeSignatureChanges);auto value =CalculateAccuracyRatio(note->Position, currentPosition, positionDelta);    std::cout << value << std::endl;// 0.64return0;}
GDScript
extendsNodefunc_ready()->void:varseconds=2varresolution=192varposition_delta=50vartempo_changes= [{"position":0,"bpm":120000 }]vartime_signature_changes= [{"position":0,"numerator":4,"denominator":2 }]varcurrent_position=rhythm_game_utilities.convert_seconds_to_ticks(seconds,resolution,tempo_changes,time_signature_changes)varvalue=rhythm_game_utilities.calculate_accuracy_ratio(750,current_position,position_delta)print(round(value*100)/100.0)# 0.64

Utilities.CalculateBeatBars

Languages:C#C++GDScript

C#
vartempoChanges=newTempo[]{new(){Position=0,BPM=88000},new(){Position=3840,BPM=112000},new(){Position=9984,BPM=89600},new(){Position=22272,BPM=112000},new(){Position=33792,BPM=111500},new(){Position=34560,BPM=112000},new(){Position=42240,BPM=111980}};varbeatBars=Utilities.CalculateBeatBars(tempoChanges);Console.WriteLine(beatBars.Length);// 440
C++
#include<iostream>#include"RhythmGameUtilities/Utilities.hpp"usingnamespaceRhythmGameUtilities;intmain(){constint resolution =192;constint timeSignature =4;    std::vector<Tempo> tempoChanges = {        {0,88000},      {3840,112000},  {9984,89600},  {22272,112000},        {33792,111500}, {34560,112000}, {42240,111980}};auto beatBars =CalculateBeatBars(tempoChanges, resolution, timeSignature,true);    std::cout <<size(beatBars) << std::endl;// 440return0;}
GDScript
extendsNodefunc_ready()->void:varresolution=192vartime_signature=4vartempo_changes= [{"position":0,"bpm":8800 },{"position":3840,"bpm":112000 },{"position":9984,"bpm":89600 },{"position":22272,"bpm":112000 },{"position":33792,"bpm":111500 },{"position":34560,"bpm":112000 },{"position":42240,"bpm":111980 }]varbeat_bars=rhythm_game_utilities.calculate_beat_bars(tempo_changes,resolution,time_signature,true)print(beat_bars)

Utilities.ConvertSecondsToTicks

Languages:C#C++GDScript

C#
usingSystem;usingRhythmGameUtilities;constintseconds=5;constintresolution=192;vartempoChanges=newTempo[]{new(){Position=0,BPM=88000},new(){Position=3840,BPM=112000},new(){Position=9984,BPM=89600},new(){Position=22272,BPM=112000},new(){Position=33792,BPM=111500},new(){Position=34560,BPM=112000},new(){Position=42240,BPM=111980}};vartimeSignatureChanges=newTimeSignature[]{new(){Position=0,Numerator=4,Denominator=2}};varticks=Utilities.ConvertSecondsToTicks(seconds,resolution,tempoChanges,timeSignatureChanges);Console.WriteLine(ticks);// 1408
C++
#include<iostream>#include"RhythmGameUtilities/Utilities.hpp"usingnamespaceRhythmGameUtilities;intmain(){constint seconds =5;constint resolution =192;    std::vector<Tempo> tempoChanges = {        {0,88000},      {3840,112000},  {9984,89600},  {22272,112000},        {33792,111500}, {34560,112000}, {42240,111980}};    std::vector<TimeSignature> timeSignatureChanges = {{0,4,2}};auto ticks =ConvertSecondsToTicks(seconds, resolution, tempoChanges,                                       timeSignatureChanges);    std::cout << ticks << std::endl;// 1408return0;}
GDScript
extendsNodefunc_ready()->void:varseconds=5varresolution=192vartempo_changes= [{"position":0,"bpm":88000 },{"position":3840,"bpm":112000 },{"position":9984,"bpm":89600 },{"position":22272,"bpm":112000 },{"position":33792,"bpm":111500 },{"position":34560,"bpm":112000 },{"position":42240,"bpm":111980 }]vartime_signature_changes= [{"position":0,"numerator":4,"denominator":2 }]varcurrent_position=rhythm_game_utilities.convert_seconds_to_ticks(seconds,resolution,tempo_changes,time_signature_changes)print(current_position)# 1408

Utilities.ConvertTickToPosition

Languages:C#C++GDScript

C#
usingSystem;usingRhythmGameUtilities;constinttick=1056;constintresolution=192;varposition=Utilities.ConvertTickToPosition(tick,resolution);Console.WriteLine(position);// 5.5
C++
#include<iostream>#include"RhythmGameUtilities/Utilities.hpp"usingnamespaceRhythmGameUtilities;intmain(){constint tick =1056;constint resolution =192;auto position =ConvertTickToPosition(tick, resolution);    std::cout << position << std::endl;// 5.5return0;}
GDScript
extendsNodefunc_ready()->void:vartick=1056varresolution=192varposition=rhythm_game_utilities.convert_tick_to_position(tick,resolution)print(position)# 5.5

Utilities.FindPositionNearGivenTick

Languages:C#C++GDScript

C#
varnotes=newNote[]{new(){Position=768},new(){Position=960},new(){Position=1152},new(){Position=1536},new(){Position=1728},new(){Position=1920},new(){Position=2304},new(){Position=2496},new(){Position=2688},new(){Position=3072},new(){Position=3264}};varnote=Utilities.FindPositionNearGivenTick(notes,750);if(note!=null){Console.Write(note.Value.Position);// 768}
C++
#include<iostream>#include"RhythmGameUtilities/Utilities.hpp"usingnamespaceRhythmGameUtilities;intmain(){    std::vector<Note> notes = {{768,0,0},  {960,0,0},  {1152,0,0},                               {1536,0,0}, {1728,0,0}, {1920,0,0},                               {2304,0,0}, {2496,0,0}, {2688,0,0},                               {3072,0,0}, {3264,0,0}};auto note =FindPositionNearGivenTick(notes,750);if (note)    {        std::cout << note->Position << std::endl;// 768    }return0;}
GDScript
extendsNodefunc_ready()->void:varseconds=5varresolution=192vardelta=50varnotes= [{"position":768 }, {"position":960 }, {"position":1152 },{"position":1536 }, {"position":1728 }, {"position":1920 },{"position":2304 }, {"position":2496 }, {"position":2688 },{"position":3072 }, {"position":3264 }]varnote=rhythm_game_utilities.find_position_near_given_tick(notes,750,delta);print(note["position"])# 768

Utilities.IsOnTheBeat

Languages:C#C++GDScript

C#
usingSystem;usingRhythmGameUtilities;constintbpm=120;constfloatcurrentTime=10f;constfloatdelta=0.05f;varisOnTheBeat=Utilities.IsOnTheBeat(bpm,currentTime,delta);Console.WriteLine(isOnTheBeat?"Is on the beat!":"Is not on the beat!");// "Is on the beat!"
C++
#include<iostream>#include"RhythmGameUtilities/Utilities.hpp"usingnamespaceRhythmGameUtilities;intmain(){constint bpm =120;constfloat currentTime =10;constfloat delta =0.05f;auto isOnTheBeat =IsOnTheBeat(bpm, currentTime, delta);    std::cout << (isOnTheBeat ?"Is on the beat!" :"Is not on the beat!")              << std::endl;// "Is on the beat!"return0;}
GDScript
extendsNodefunc_ready()->void:varbpm=120varcurrent_time=10vardelta=0.05varisOnTheBeat=rhythm_game_utilities.is_on_the_beat(bpm,current_time,delta)ifisOnTheBeat:# "Is on the beat!"print("Is on the beat!")else:print("Is not on the beat!")

Utilities.RoundUpToTheNearestMultiplier

Languages:C#C++GDScript

C#
usingSystem;usingRhythmGameUtilities;varvalue=Utilities.RoundUpToTheNearestMultiplier(12,10);Console.WriteLine(value);// 20
C++
#include<iostream>#include"RhythmGameUtilities/Utilities.hpp"usingnamespaceRhythmGameUtilities;intmain(){auto value =RoundUpToTheNearestMultiplier(12,10);    std::cout << value << std::endl;// 20return0;}
GDScript
extendsNodefunc_ready()->void:varvalue=rhythm_game_utilities.round_up_to_the_nearest_multiplier(12,10)print(value)# 20

Architecture

The current architecture for this project looks like this:

C++ Library / C# Plugin

graph LR;    file[/"song.chart"/]    subgraph audioGraph ["Audio"]        convertSamplesToWaveform["ConvertSamplesToWaveform()"]    end    subgraph commonGraph ["Common"]        inverseLerp["InverseLerp()"]        lerp["Lerp()"]    end    subgraph parsersGraph ["Parsers"]        parseSectionsFromChart["ParseSectionsFromChart()"]        parseLyricsFromChartSection["ParseLyricsFromChartSection()"]        parseMetaDataFromChartSection["ParseMetaDataFromChartSection()"]        parseNotesFromChartSection["ParseNotesFromChartSection()"]        parseTempoChangesFromChartSection["ParseTempoChangesFromChartSection()"]        parseTimeSignaturesChangesFromChartSection["ParseTimeSignatureChangesFromChartSection()"]        parseSectionsFromChart-->parseLyricsFromChartSection        parseSectionsFromChart-->parseMetaDataFromChartSection        parseSectionsFromChart-->parseNotesFromChartSection        parseSectionsFromChart-->parseTempoChangesFromChartSection        parseSectionsFromChart-->parseTimeSignaturesChangesFromChartSection    end    subgraph utilitiesGraph ["Utilities"]        calculateAccuracyRatio["CalculateAccuracyRatio()"]        calculateBeatBars["CalculateBeatBars()"]        convertSecondsToTicks["ConvertSecondsToTicks()"]        convertTickToPosition["ConvertTickToPosition()"]        isOnTheBeat["IsOnTheBeat()"]        roundUpToTheNearestMultiplier["RoundUpToTheNearestMultiplier()"]    end    file-->parseSectionsFromChart    convertSecondsToTicks-->calculateAccuracyRatio    parseMetaDataFromChartSection-->calculateAccuracyRatio    parseNotesFromChartSection-->calculateAccuracyRatio    parseMetaDataFromChartSection-->calculateBeatBars    parseTempoChangesFromChartSection-->calculateBeatBars    parseMetaDataFromChartSection-->convertSecondsToTicks    parseTempoChangesFromChartSection-->convertSecondsToTicks    parseTimeSignaturesChangesFromChartSection-->convertSecondsToTicks    parseMetaDataFromChartSection-->convertTickToPosition    parseMetaDataFromChartSection-->isOnTheBeat
Loading

Unity Plugin

The Unity plugin includes compiled C++ libraries (macOS, Windows and Linux) and wraps the internal calls in native C# functions. These functions pass and retrieve the data from the C++ library and clean up memory upon completion.

Unreal Plugin

There isn't a custom wrapper or plugin for Unreal, as the C++ library works as is when included as a header-only library.

Godot Plugin

Coming soon.

SDL Library

There isn't a custom wrapper or plugin for SDL, as the C++ library works as is when included as a header-only library.

Git Hooks

The git hooks that run are quick file checks to ensure the files in the dotnet project and the UnityProject are the same and that the build files haven't changed.

$ git config --local core.hooksPath .githooks/

Testing

Run all tests viamake test.

  • Tests for the C++ library are authored using the C++ native librarycassert.
  • Tests are run automatically via GitHub Actions on each new PR.
  • For you add a new feature or fix a bug, please include the benchmark output in the PR along with your device stats.

If you want to test the project from within Unity, add the test namespace to your project by adding the following to yourPackages/manifest.json file:

{..."testables": ["com.scottdoxey.rhythm-game-utilities"]...}

Build

Warning

Do not commit any build changes to the repo. The build files are automatically generated via GitHub Actions.

macOS

When developing on macOS, make sure thatMac is selected in the bottom right-hand corner of Visual Studio Code or C++ Intellisense will not work.

./bin/build.sh

Windows

When developing on Windows, make sure thatWin32 is selected in the bottom right-hand corner of Visual Studio Code or C++ Intellisense will not work.

Run fromx64 Native Tools Command Prompt for VS:

call"./bin/build.bat"

Contributing

Be sure to review theContributing Guidelines before logging an issue or making a pull request.

Community Roadmap

This project aims to help you build your rhythm game as fast as possible without needing to learn the complexities of a new library. Instead, you can utilize comprehensive examples and simple code recipes If you have feature requests or bugs, please create an issue and tag them with the appropriate tag. If an issue already exists, vote for it with 👍.

Other Projects

NameDescriptionLink
tiny-midiTiny wrapper around Window/macOS native MIDI libraries for reading MIDI input.https://github.com/neogeek/tiny-midi
chart-to-jsonParse .chart files in JavaScript or the command line.https://github.com/neogeek/chart-to-json

License

The MIT License (MIT)

About

A collection of utilities for creating rhythm games in Unity, Unreal, Godot, SDL and MonoGame.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

    Languages


    [8]ページ先頭

    ©2009-2025 Movatter.jp