Skip to article Developer portalAnnounce, upload and sell your game

GAMENIGHT / DOCUMENTATION

LÖVE / Lua

Use the shared runner in the separate ontola/gamenight-games repository. It handles the GameNight connection, hidden preparation, pause/resume, window switching and host controller input. The bundled games use this path.

Run the reference game

Install LÖVE 11.5, clone the repository and run from its root:

python scripts/fetch-game-sources.py
love ../gamenight-games/love-party

The fetch command checks out the revision in game-sources.json beside the host repository. For local edits, set GAMENIGHT_GAMES_DIR to your game checkout before testing or packaging.

This starts the standalone menu. The host supplies GAMENIGHT=1, its address, game ID and launch token when launching a managed build. Do not set a made-up token yourself.

Add your game module

Keep simulation in a game module and leave lifecycle handling in the runner. A module defines new(players, rng) and update(state, dt, inputs). This is the beginning of the real Neon Trails module:

function M.new(players, rng)
	local s = { players = players, rng = rng }
	reset(s)
	return s
end
function M.update(s, dt, inputs)
	if s.intermission then
		s.intermission = s.intermission - dt
		if s.intermission <= 0 then
			reset(s)
		end
		return
	end
	for i, p in ipairs(s.players) do
		local c = inputs[i]
		local dx, dy = 0, 0
		if math.abs(c.x) > math.abs(c.y) and math.abs(c.x) > 0.3 then
			dx = c.x > 0 and 1 or -1
		elseif math.abs(c.y) > 0.3 then
			dy = c.y > 0 and 1 or -1
		end
		if dx ~= 0 or dy ~= 0 then
			if dx ~= -p.dx or dy ~= -p.dy then
				p.nextX, p.nextY = dx, dy
			end
		end
	end

Source: games/love-party/games/trails.lua

The input entries belong to the supplied player slots. Do not replace them with love.joystick.getJoysticks() in managed mode. The shared input adapter neutralises disconnected devices and frames older than 250 ms.

Register a new module in modes in main.lua, add its renderer and add its ID to GAMES in the packaging script. These are explicit registries, not automatic plugin discovery. Use an existing game as the full worked example.

Draw a player face

local Face = require("shared.face")
Face.drawFace(player, x, y, 24, { facing = -1 })

x and y are the centre of the head. The helper draws the skin circle before the transparent artwork, retains space for hats and handles live artwork changes. See Faces & colours.

Keep the shared window path

Use shared.window and shared.back_gate. Prepare before showing the window. Back needs a fresh press after release, and a focus event must never resume a paused game. Keep borderless fullscreen and the helper’s Windows presentation workaround.

Package and test

python scripts/test-love-simulation.py
python scripts/package-love-party.py --output dist/my-party-build

The output directory must be new. Packaging builds the registered titles; it does not automatically publish them. Run the integration suite against the resulting packages, then check real controllers and window switching on each target OS.

Optional performance diagnostics

The bundled launcher samples application frame intervals while running and reports them every ten active seconds. It includes GPU, OS and pixel dimensions; CPU and RAM are unavailable. Standalone games send nothing. See the protocol reference for counters, limits and missing-data semantics. These diagnostics contain no accounts, behavioral history or recommendation logic.

Game settings

Use the settings helper and game reference to expose choices, toggles and bounded numbers to the lobby and phone. Validate each change and snapshot round rules when creating a round.