ChiptuneSfxPlayer2D
Extends AudioStreamPlayer2D. Read from the plugin's source on every build.
A sound the game fires from a place on screen, panned and quieter with
distance. An AudioStreamPlayer2D that plays a .sfx.tres.
ChiptuneSfxPlayer placed in 2D, and a game changes it the same way. Fire
it: play, play_at. Repeats that differ: variants,
pitch_variance. The same variety every run: seed. One
node’s own copy: unique.
A class of its own, since Godot’s players descend from Node and Node2D and
share no ancestor that has a stream. Both hand the document to
ChiptuneAudioStream.for_document. For 3D, put a ChiptuneAudioStream on
Godot’s own AudioStreamPlayer3D.
Properties
document
@export_custom(PROPERTY_HINT_RESOURCE_TYPE, "ChiptuneSfxSpec") var document: ResourceThe .sfx.tres to play.
Hinted to ChiptuneSfxSpec alone so the picker and its Quick Load search
offer sounds and not every resource in the project. A song belongs on a
ChiptuneSongPlayer, which has the loop. The hint is an editor filter and
not the contract: anything answering render() still plays when it is
assigned from code or written into a scene by hand, a song included. See
ChiptuneAudioStream.
unique
@export var unique := falseWhether this node plays its own copy of document, apart from the
file every other node of it shares.
Off, a script’s edit to document is heard on every node holding
the same file. On, the copy is made when the document is assigned, so
document.instrument.decay = 0.1 changes this node alone; the
scene still stores the file. A save of the file while the game runs copies
it again, and the node’s own edits go with it. In the editor the node holds
the file, so the inspector shows what the scene stores.
Declared after document, so the file comes first in the inspector.
A scene the editor saves sets it after the document has rendered, and the
copy it makes then sounds the same, so it is held without a second render.
pitch_variance
@export_range(0, 12) var pitch_variance := 0How far each play may wander from the pitch it was asked for, in semitones either way, rolled per play. Zero plays it where it is.
Nothing is rendered for it, so it is free; a sound played higher is also shorter, as any sample is.
variants
@export_range(1, 8) var variants := 1How many versions of the sound this node takes in turn, one per play: at
one, the document as it is; above one, that many variations on it, each a
ChiptuneSfx.nudge of the document on the document’s note,
rendered once when it loads and again when it changes.
Each variant keeps the wave, the arpeggio and the note and nudges every other number a little, so a hit is not the same hit twice.
seed
@export var seed := 0Which variations variants makes: the same seed is the same set of
sounds, taken in the same order.
Methods
play_at
func play_at(pitch: int, from_position := 0.0) -> voidPlays the sound at the MIDI note pitch, sixty being middle C, by
setting AudioStreamPlayer.pitch_scale from how far it is from the
document’s own ChiptuneSfxSpec.pitch. Nothing is rendered, so a
coin that climbs a step per pickup costs what play does.
The pitch_scale goes back to what it was when the sound ends, or at the
next play() made through this node’s script. A
play() the engine takes directly while the sound is still
sounding, from a variable typed ChiptuneSfxPlayer or autoplay, plays at
the note asked for here.
play
func play(from_position := 0.0) -> voidAudioStreamPlayer.play, back at the document’s pitch after a
play_at. Only that: the variants and the spread are picked by the
engine, on every play.
rebuild
func rebuild() -> voidRenders document now, for a change the same frame has to hear;
a change on its own is heard on the next idle frame. The same call
ChiptuneSfxPlayer has, and the same cost: see the module README.
Signals
document_changed
signal document_changedEmitted after new audio for document lands in this node’s stream,
whatever asked for it: the document changing, rebuild, a save.
JamChip, by GlitterSnack. MIT licence. Built from the source on every merge. Its artwork and screenshots are made with JamChip.