06. Setting up Development Server
For rest of the guide, we will be creating a one-lane-tap-only rhythm game engine, as well as a level to go along with it, as a real world example.
In this chapter, we will go over setting up development server using Sonolus.js.
Required Resources
The primary purpose of Sonolus.js is for developing engines, so its development server requires Engine Configuration and Engine Data, as well as Level Data for a test level.
Engine Configuration
Engine configuration contains:
- Options: provide a way for players to adjust engine specific settings.
- UI: allows player to adjust visibility and animation of various gameplay UI elements.
We don't need any options for now:
const options = defineOptions({})
const options = defineOptions({})
For UI we can use some placeholder values and adjust in the future:
const ui: EngineConfigurationUI = {
primaryMetric: 'arcade',
secondaryMetric: 'life',
menuVisibility: {
alpha: 1,
scale: 1,
},
judgmentVisibility: {
alpha: 1,
scale: 1,
},
comboVisibility: {
alpha: 1,
scale: 1,
},
primaryMetricVisibility: {
alpha: 1,
scale: 1,
},
secondaryMetricVisibility: {
alpha: 1,
scale: 1,
},
judgmentAnimation: {
scale: {
from: 1,
to: 1,
duration: 0,
ease: 'Linear',
},
alpha: {
from: 1,
to: 1,
duration: 0,
ease: 'Linear',
},
},
comboAnimation: {
scale: {
from: 1,
to: 1,
duration: 0,
ease: 'Linear',
},
alpha: {
from: 1,
to: 1,
duration: 0,
ease: 'Linear',
},
},
judgmentErrorStyle: 'none',
judgmentErrorPlacement: 'both',
judgmentErrorMin: 0,
}
const ui = {
primaryMetric: 'arcade',
secondaryMetric: 'life',
menuVisibility: {
alpha: 1,
scale: 1,
},
judgmentVisibility: {
alpha: 1,
scale: 1,
},
comboVisibility: {
alpha: 1,
scale: 1,
},
primaryMetricVisibility: {
alpha: 1,
scale: 1,
},
secondaryMetricVisibility: {
alpha: 1,
scale: 1,
},
judgmentAnimation: {
scale: {
from: 1,
to: 1,
duration: 0,
ease: 'Linear',
},
alpha: {
from: 1,
to: 1,
duration: 0,
ease: 'Linear',
},
},
comboAnimation: {
scale: {
from: 1,
to: 1,
duration: 0,
ease: 'Linear',
},
alpha: {
from: 1,
to: 1,
duration: 0,
ease: 'Linear',
},
},
judgmentErrorStyle: 'none',
judgmentErrorPlacement: 'both',
judgmentErrorMin: 0,
}
Finally putting them together is as simple as:
const engineConfiguration = {
options,
ui,
}
const engineConfiguration = {
options,
ui,
}
Engine Data
Engine data contains:
- Buckets: provides a way for players to visualize their judgments on different types of notes.
- Archetypes: abstractions of entities that share common behaviors and data.
- Scripts: abstractions of archetype behaviors.
We will skip buckets for now:
const buckets = defineBuckets({})
const buckets = defineBuckets({})
For now, we have only an initialization
script which simply sets up UI Menu in preprocess so we can exit:
const scripts = defineScripts({
initialization: () => ({
preprocess: UIMenu.set(
Subtract(0.05, ScreenAspectRatio),
0.95,
0,
1,
0.15,
0.15,
0,
1,
HorizontalAlign.Center,
true
),
}),
})
const scripts = defineScripts({
initialization: () => ({
preprocess: UIMenu.set(
Subtract(0.05, ScreenAspectRatio),
0.95,
0,
1,
0.15,
0.15,
0,
1,
HorizontalAlign.Center,
true
),
}),
})
And an initialization
archetype using initialization
script:
const archetypes = defineArchetypes({
initialization: scripts.initializationIndex,
})
const archetypes = defineArchetypes({
initialization: scripts.initializationIndex,
})
Finally putting them together:
const engineData = {
buckets,
archetypes,
scripts,
}
const engineData = {
buckets,
archetypes,
scripts,
}
Level Data
Level data contains:
- Entities: a list of entities to be spawned in the level.
For now, we have only one entity of initialization
archetype:
const levelData = {
entities: [
{
archetype: archetypes.initializationIndex,
},
],
}
const levelData = {
entities: [
{
archetype: archetypes.initializationIndex,
},
],
}
Building
With these information, we can call build
to build them into formats Sonolus can understand:
const buildOutput = build({
engine: {
configuration: engineConfiguration,
data: engineData,
},
level: {
data: levelData,
},
})
const buildOutput = build({
engine: {
configuration: engineConfiguration,
data: engineData,
},
level: {
data: levelData,
},
})
Serving
Finally we can serve it with a development server by calling serve
:
serve(buildOutput)
serve(buildOutput)
Try connecting to one of the addresses listed using Sonolus app and if it works, we are ready to develop our engine!