Scripting - JoaTH-Team/Rhythmo-SC GitHub Wiki
Scripts in Rhythmo can be active in only one song, or be applied globally to every song. You can use scripts to make custom backgrounds, add special functions, make cool mechanics, etc.
Your script should either be located in assets/scripts/
, or in assets/songs/[song-name]/
.
However, if your script is a scripted state or substate, it should be located in assets/states/
or assets/substates/
.
Currently, the following extensions are supported:
.hscript
.hx
.hxc
.hxs
.lua
The following are not supported:
- Keywords:
-
package
,import
(another function emulates this),class
,typedef
,metadata
,final
-
- Wildcard imports (
import flixel.*
) - Access modifiers (e.g.,
private
,public
)
-
Function_Stop
- Cancels functions (e.g.,startCountdown
,endSong
). -
Function_Continue
- Continues the game like normal. -
platform
- Returns the current platform (e.g., Windows, Linux). -
version
- Returns the current game version.
-
import(daClass:String, ?asDa:String)
- See Imports for more. -
trace(value:Dynamic)
- The equivalent oftrace
in normal Haxe. -
stopScript()
- Stops the current script. -
addScript(path:String)
- Adds a new script during gameplay (PlayState). -
importScript(source:String)
- Gives access to another script's local functions and variables.
To import a class, use:
import('package.Class');
To import an enumerator, use:
import('package.Enum');
To import with an alias, use:
import('package.Class', 'Name');
var aliasClass:Name;
You can basically use this to import any class/enum you'd like.
Otherwise, here is a list of the current classes you can use that are already imported:
Array
Bool
Date
DateTools
Dynamic
EReg
Float
Int
Lambda
Math
Reflect
Std
String
StringBuf
StringTools
Sys
Type
Xml
Achievements
Application
Assets
Bar
Conductor
DiscordClient
ExtendableState
ExtendableSubState
File
FileSystem
FlxAxes
FlxBackdrop
FlxBasic
FlxCamera
FlxCameraFollowStyle
FlxColor
FlxEase
FlxG
FlxGroup
FlxMath
FlxObject
FlxRuntimeShader
FlxSound
FlxSprite
FlxSpriteGroup
FlxText
FlxTextAlign
FlxTextBorderStyle
FlxTimer
FlxTween
FlxTypedGroup
GameSprite
HighScore
Input
Json
Lib
Localization
LuaScript
Main
ModHandler
Note
Path
Paths
PlayState
Rating
SaveData
ScriptedState
ScriptedSubState
Song
TJSON
Utilities
Some useful templates to get started. For the default template, use this.
import('flixel.FlxSprite');
import('states.PlayState');
function create() {
var spr:FlxSprite = new FlxSprite(0, 0).makeGraphic(50, 50, FlxColor.BLACK);
add(spr);
}
import('flixel.FlxSprite');
import('states.PlayState');
import('backend.Paths');
function create() {
var spr:FlxSprite = new FlxSprite(0, 0).loadGraphic(Paths.image('gameplay/banan'), true, 102, 103);
spr.animation.add('rotate', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], 14);
spr.animation.play('rotate');
spr.screenCenter();
add(spr);
}
import('flixel.text.FlxText');
import('states.PlayState');
function create() {
var text:FlxText = new FlxText(0, 0, 0, "Hello World", 64);
text.screenCenter();
add(text);
}
import('sys.FileSystem');
import('sys.io.File');
import('haxe.Json');
var json:Dynamic;
function create() {
if (FileSystem.exists('assets/data.json'))
json = Json.parse(File.getContent('assets/data.json'));
trace(json);
}
import('states.ScriptedState');
import('substates.ScriptedSubState');
import('backend.ExtendableState');
import('flixel.text.FlxText');
import('flixel.FlxSprite');
import('backend.Input');
function create() {
var bg:FlxSprite = new FlxSprite(0, 0).makeGraphic(1280, 720, FlxColor.WHITE);
add(bg);
var text:FlxText = new FlxText(0, 0, FlxG.width, "I am a custom state!", 48);
text.color = FlxColor.BLACK;
add(text);
}
function update(elapsed:Float) {
if (Input.justPressed('accept'))
ExtendableState.switchState(new ScriptedState('name', [/* arguments, if any */])); // load custom state
if (Input.justPressed('exit'))
openSubState(new ScriptedSubState('name', [/* arguments, if any */])); // load custom substate
}
Additionally, if you want to load your custom state from the main menu, navigate to assets/data/menuList.txt
and add in your state's name, as well as a main menu asset for it in assets/images/menu/mainmenu/[name].png
.
And just in case your script doesn't load or something goes wrong, press F4
to be sent to the main menu.
Script 1:
// assets/helpers/spriteHandler.hxs
import('flixel.FlxSprite');
import('backend.Paths');
function createSprite(x:Float, y:Float, graphic:String) {
var spr:FlxSprite = new FlxSprite(x, y);
spr.loadGraphic(Paths.image(graphic));
add(spr);
trace("sprite " + sprite + " created");
}
Script 2:
var otherScript = importScript('helpers.spriteHandler');
function create() {
otherScript.createSprite(0, 0, 'sprite');
}
import('flixel.addons.display.FlxRuntimeShader');
import('openfl.filters.ShaderFilter');
import('openfl.utils.Assets');
import('flixel.FlxG');
import('backend.Paths');
var shader:FlxRuntimeShader;
var shader2:FlxRunTimeShader;
function create() {
shader = new FlxRuntimeShader(Assets.getText(Paths.frag('rain')), null);
shader.setFloat('uTime', 0);
shader.setFloatArray('uScreenResolution', [FlxG.width, FlxG.height]);
shader.setFloat('uScale', FlxG.height / 200);
shader.setFloat("uIntensity", 0.5);
shader2 = new ShaderFilter(shader);
FlxG.camera.filters = [shader2];
}
function update(elapsed:Float) {
shader.setFloat("uTime", shader.getFloat("uTime") + elapsed);
shader.setFloatArray("uCameraBounds", [
FlxG.camera.scroll.x + FlxG.camera.viewMarginX,
FlxG.camera.scroll.y + FlxG.camera.viewMarginY,
FlxG.camera.scroll.x + FlxG.camera.width,
FlxG.camera.scroll.y + FlxG.camera.height
]);
}
-
Function_Stop
- Cancels functions (e.g., startCountdown, endSong). -
Function_Continue
- Continues the game like normal. -
platform
- Returns the current platform (e.g., Windows, Linux). -
version
- Returns the current game version. -
lua.version
- Returns the current lua version. -
lua.versionJIT
- Returns the current luajit version.
-
trace(value:Dynamic)
- The equivalent oftrace
in normal Haxe.- Additionally, you can also use
print
instead.
- Additionally, you can also use
-
stopScript()
- Stops the current script. -
stdInt(x:Float)
- Converts a floating point number into an integer.
-
createObject(type:String, tag:String, config:Dynamic)
- Creates an object with a specific configuration. -
addObject(tag:String)
- Adds an object. -
removeObject(tag:String)
- Removes an object. -
insertObject(tag:String, pos:Int = 0)
- Inserts an object at a specific position. -
setPosition(tag:String, x:Float, y:Float)
- Sets an object's position. -
setScale(tag:String, x:Float, y:Float)
- Sets the scaling of an object. -
setProperty(tag:String, property:String, value:Dynamic)
- Sets the property of an object. -
getProperty(tag:String, property:String)
- Gets the property of an object.
-
createObject("text", "tag", {x = 0, y = 0, width = 0, text = "Text goes here.", size = 16})
- Creates a text object. -
setText(tag:String, newText:String)
- Changes the current text for a text object. -
configText(tag:String, config:Dynamic)
- Configures a text object with various properties.-
x
,y
: Position -
width
: Text width -
text
: Text content -
size
: Font size -
color
: Text color -
alignment
: Text alignment -
alpha
: Transparency -
scale
: Scaling -
angle
: Rotation angle -
visible
: Visibility -
active
: Active -
scrollFactor
: Scroll speed -
antialiasing
: Anti-aliasing -
font
: Custom font -
borderSize
: Text border size -
borderColor
: Border color -
borderStyle
: Border style -
borderQuality
: Border quality
-
-
createObject("sprite", "tag", {x = 0, y = 0, image = "image"})
- Creates a sprite. -
makeAnimationSprite(tag:String, x:Float, y:Float, path:String)
- Creates an animated sprite. -
addAnimationByPrefix(tag:String, name:String, prefix:String, fps:Int, looped:Bool)
- Adds an animation to an animated sprite. -
playAnimation(tag:String, name:String, force:Bool = false, rev:Bool = false, frames:Int = 0)
- Plays an animation for an animated sprite. -
configSprite(tag:String, config:Dynamic)
- Configures a sprite with various properties.-
image
: Image path -
x
,y
: Position -
width
,height
: Dimensions -
alpha
: Transparency -
scale
: Scaling -
angle
: Rotation angle -
visible
: Visibility -
active
: Active -
scrollFactor
: Scroll speed
-
-
playSound(name:String, volume:Float, loop:Bool)
- Plays a sound. -
playMusic(name:String, volume:Float, loop:Bool)
- Plays music.
-
runHaxeCode(code:String)
- Runs Haxe code. -
runHaxeFunction(func:String, ?args:Array<Dynamic>)
- Runs a Haxe function. -
importHaxeLibrary(lib:String, ?packageName:String)
- Imports a Haxe library.
-
getInput(state:String, key:String)
- Checks for a specific input.
For the default template, use this.
function create()
createObject("sprite", "sun", {x = 0, y = 0, image = "sun"})
addObject("sun")
end
function create()
makeAnimationSprite("player", 500, 0, "example")
addAnimationByPrefix("player", "idle", "Idle", 24, false)
addAnimationByPrefix("player", "singUP", "Up", 24, true)
addAnimationByPrefix("player", "singDOWN", "Down", 24, true)
addAnimationByPrefix("player", "singLEFT", "Left", 24, true)
addAnimationByPrefix("player", "singRIGHT", "Right", 24, true)
playAnimation("player", "idle", false, false, 0)
addObject("player")
end
function update(elapsed)
if getInput("pressed", "LEFT") then
playAnimation("player", "singLEFT", true, false, 0)
elseif getInput("pressed", "RIGHT") then
playAnimation("player", "singRIGHT", true, false, 0)
elseif getInput("pressed", "UP") then
playAnimation("player", "singUP", true, false, 0)
elseif getInput("pressed", "DOWN") then
playAnimation("player", "singDOWN", true, false, 0)
else
playAnimation("player", "idle", false, false, 0)
end
end
function create()
createObject("text", "tutoText", {x = screenWidth / 2, y = screenHeight / 2, width = 0, text = "Press the notes!", size = 64})
configText("tutoText", {font = "vcr"})
addObject("tutoText")
end
function create()
importHaxeLibrary("FlxG", "flixel")
runHaxeCode([[
FlxG.openURL("https://github.com/JoaTH-Team/Rhythmo-SC");
]])
end
If you need any general help or something goes wrong with your script, report an issue here.