procgen

package
v0.0.52 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 4, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package procgen generates the Linefire procedural map as a grid of chunks. A chunk is one square tile of the world (walls + spawns) produced deterministically from a world seed and the chunk coordinates, so the same chunk always looks the same — and once generated it is saved, so prior generation (and, later, server edits) is reused instead of regenerated. The map feels endless because the game only keeps the 3x3 neighbourhood around the player loaded, streaming new chunks in as the ship moves.

Index

Constants

View Source
const (
	DefaultArenaW = 2400.0
	DefaultArenaH = 1600.0
)

DefaultArenaW and DefaultArenaH are used when a caller passes no size. Big enough that a fight spreads out, walled so nothing can leave.

View Source
const (
	EdgeLeft = iota
	EdgeRight
	EdgeTop
	EdgeBottom
)

Edge sides: which side of a generated screen the player arrives on (and, for the caller, which map edge the player breached — the two are opposite).

View Source
const ChunkSize = 1200.0

ChunkSize is the world-unit side length of one chunk.

Variables

This section is empty.

Functions

func CaveArenaSize added in v0.0.26

func CaveArenaSize(w, h float64) (float64, float64)

CaveArenaSize is the size GenCaveArena would produce for a requested one: the cave is carved on a cell grid, so the arena snaps down to whole cells. A caller that fits the arena to a view compares against this, not against the raw request. Zero or less takes the cave generator's classic square.

func ChunkCenter

func ChunkCenter(cx, cy int) (float64, float64)

ChunkCenter returns the world-space center of chunk (cx, cy).

func ChunkOf

func ChunkOf(x, y float64) (int, int)

ChunkOf returns the chunk coordinates containing world point (x, y).

func GenArena added in v0.0.20

func GenArena(seed int64, w, h float64) *level.Level

GenArena builds an open field of the given size in world units — zero or less takes the default: a walled rectangle and nothing else inside it.

It is the counterpart to GenCaveRoom, for a battle that is NOT meant to happen in a cave. The perimeter exists for PHYSICS, not for the eye: it declares no stroke and no glow, so nothing is ever drawn for it. An open field has no fence — a caller that fits the arena to a screen gets the screen edge (or the window frame) as the visible border, which is the point. Collision does not care: wall segments are read from the paths regardless of how the layer looks.

Spawns are left to the caller: an arena is a place to fight, not a stage.

func GenCaveArena added in v0.0.26

func GenCaveArena(seed int64, w, h float64) *level.Level

GenCaveArena builds a labyrinth arena close to the given size in world units (snapped down to whole cave cells — see CaveArenaSize): the cave generator fitted to a screen, for a battle among rock walls instead of in the open. Unlike GenArena's invisible fence, a maze IS its walls, so the layer keeps the cave's stroke and glow.

Like GenArena it ships no spawns — an arena is a place to fight, not a stage. PlayerStart is the most open cell near the bottom of the carved region, so a caller that parks something there has it in reachable open space.

func GenCaveRoom

func GenCaveRoom(seed int64, exitTarget string) *level.Level

GenCaveRoom builds a bonus cave stage for the seed, with an exit portal targeting exitTarget ("map:label"). It always returns a runnable level: on the rare fully-blocked seed it falls back to an open room, so callers never get an empty or broken bonus.

func GenEdgeRoom

func GenEdgeRoom(seed int64, entrySide, difficulty int, returnTarget string) *level.Level

GenEdgeRoom builds a procedural screen the player reaches by DIGGING past a map's edge: a cave entered from entrySide (so the tunnel reads as continuing), with NO exit portal — you leave it by digging on. It is deliberately harder than a normal screen, and harsher the deeper you have dug (difficulty): more guards, drawn increasingly from tanks/snipers/turrets.

func GenRiftRoom

func GenRiftRoom(seed int64, difficulty int, forwardTarget string) *level.Level

GenRiftRoom builds an ENDLESS-mode ("The Rift") screen: like an edge room — a harder cave whose guard set scales with depth — but a ONE-WAY trap. It has NO return portal; the only way onward is a forward portal to the next Rift, and it opens only when the room is cleared (a DoPortal resolution on OnCleared). This is what the player falls into by taking the boss's portal: no exit but death. forwardTarget is the reserved runtime name that regenerates the next Rift ("@rift").

Types

type Chunk

type Chunk struct {
	CX, CY int
	Walls  []asset.Layer
	Spawns []level.Spawn
}

Chunk is one generated tile: walls and spawns already in WORLD coordinates (offset to the chunk's position), so chunks stitch together without translation.

func GenBlocks

func GenBlocks(seed int64, cx, cy int) Chunk

GenBlocks is the default chunk algorithm: a mostly-open arena with a clear border ring (so neighbouring chunks always connect along the shared edge) and a clear central disc (a safe spawn / crossing lane), with scattered rectangular wall blocks and a few enemies in the open. Fully deterministic in (seed, cx, cy).

type Generator

type Generator func(seed int64, cx, cy int) Chunk

Generator turns a seed and chunk coordinates into a chunk. The default is GenBlocks; swapping it is how different map algorithms are tried.

type World

type World struct {
	Dir  string
	Seed int64
	Gen  Generator
}

World is a procedural map instance: a seed, a directory it persists chunks to, and the algorithm that generates them.

func NewWorld

func NewWorld(dir string, seed int64) *World

NewWorld returns a world that persists under dir and generates with GenBlocks.

func (*World) Assemble

func (w *World) Assemble(cx, cy int) (*level.Level, error)

Assemble stitches the 3x3 neighbourhood around (cx, cy) into one runnable level, with the player starting at the center of the (cx, cy) chunk. Walls from every chunk merge into one layer; spawns concatenate (all already in world coords).

func (*World) Ensure

func (w *World) Ensure(cx, cy int) error

Ensure generates and saves the 3x3 neighbourhood around (cx, cy) — the chunk the player is in plus the eight around it — reusing any that already exist.

func (*World) Get

func (w *World) Get(cx, cy int) (Chunk, error)

Get returns a chunk, loading it from disk when it was generated before (so prior generation and future server edits are reused) or generating and saving it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL