Skip to content

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: Resource

The .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 := false

Whether 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 := 0

How 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 := 1

How 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 := 0

Which 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) -> void

Plays 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) -> void

AudioStreamPlayer.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() -> void

Renders 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_changed

Emitted 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.