Particles and lines
Particle emitters on the CPU and the GPU, Line2D and Trail2D.
Files: particles.odin, gpu_particles.odin, lines.odin.
File overviews
Section titled “File overviews”particles.odin
Section titled “particles.odin”Particle emitters: a ParticleEmitter node emits particles from its position, moves them
(velocity, acceleration, gravity, wind, spin), changes their size and color over their life
(a start and end color, or a ColorRamp of up to MAX_COLOR_STOPS colors) and draws them as
circles, ellipses, rectangles, pixels, lines, a texture, or with code.
Its settings (ParticleSettings) say how; scene files store the ones that differ from
DEFAULT_PARTICLE_SETTINGS in a <particles> element (project_format.odin). Their struct tags
(min, max, label, group) describe them for editors: ParticleSettings_Fields.
Emission runs in cycles of lifetime seconds: each cycle emits amount particles, spread over
the first 1 - burst of it (burst 1: all at once). A continuous emitter starts a new cycle
when one ends; otherwise it stops (ParticleEmitter_Start runs it again). A particle lives
lifetime seconds too.
Particles move in the world (they stay behind when the emitter moves; their direction turns with
its world rotation), or in its local space with localSpace (they move, turn and scale with it).
Angles are degrees clockwise from +X, like rotations; angle 270 is up.
Randomness: each xSpread is a range around the base value, used in proportion to xVariance
(0: none, 1: all of it). spread is the half-size of the area particles start in.
Collisions (collisionEnabled): particles bounce off each other and, in world space, off the
edges of what the camera shows (or the game area without a camera), keeping elasticity of
their speed. It compares every pair of live particles: keep amount low with it.
Example
sparks := e.CreateParticleEmitter(scene)sparks.position = {400, 300}sparks.settings.amount = 80sparks.settings.angle = 270sparks.settings.angleSpread = 40sparks.settings.angleVariance = 1sparks.settings.shape = .Rectangle
// A one-shot burst, e.g. an explosionboom := e.CreateParticleEmitter(scene)boom.settings.burst = 1boom.settings.continuous = falsee.ParticleEmitter_Start(boom)gpu_particles.odin
Section titled “gpu_particles.odin”GPU particles: a ParticleEmitter with gpu on simulates gpuAmount particles (up to
MAX_GPU_PARTICLES) on the graphics card, when the game draws with SDL’s GPU renderer.
How: nothing is kept per particle. The vertex shader (shaders/particles) works out each particle from its index and the time: when it was born in its cycle, where the emitter was then (the emitter’s path, recorded each update and handed over as a storage buffer), random numbers from a hash of its index and cycle, then the motion in closed form (velocity, acceleration, gravity, wind; spin), its size and its color (start and end, or the ramp: up to 8 stops). The particles are drawn into a picture of their own on SDL’s GPU device (instanced quads, the emitter’s blend: alpha or additive), which the renderer then draws where the emitter is in the scene. Measured on an Intel UHD 620 (integrated graphics), a frame’s update and draw: 500 particles on the CPU 1.6 ms; on the GPU 500 0.8 ms, 20 000 2.1 ms, 100 000 5.2 ms, 200 000 9.1 ms.
The same settings, with these differences: no collisions (the view’s edges); the Custom,
Ellipse, Line and Pixel shapes draw as circles; localSpace works. Where the GPU renderer isn’t
available (other renderers, the web) the emitter simulates on the CPU as usual, with amount
particles.
lines.odin
Section titled “lines.odin”Lines and trails: thick polylines drawn as triangles (one geometry call each).
- Line2D nodes draw a line through their points (the node’s space;
points="0,0 100,20"in scene files,Line2D_SetPoints/AddPointfrom code): ropes, lasers, paths, outlines. A width, a color fading toendColoralong it, joints (sharp, clamped toLINE_MITER_LIMITwidths, or round), round caps, closed loops, and an optional texture stretched along it or tiled everywidthpixels. - Trail2D nodes leave a ribbon behind their parent as it moves (swords, dashes, comets, tire
tracks): they record the parent’s world position as it moves at least
minDistance, forget points older thanlifetime, and draw them in the world, fromwidth/colorat the newest point toendWidth/endColorat the oldest.emittingoff stops adding points (the trail fades away);Trail2D_Clearempties it (after a teleport).
Both draw through a node’s shader (shaders.odin) when they have a texture.
Example
// Given: sword: ^e.Nodelaser := e.CreateLine2D(scene, {{0, 0}, {400, 0}})laser.settings.width = 6laser.settings.color = {255, 60, 60, 255}laser.settings.endColor = {255, 60, 60, 0}trail := e.CreateTrail2D(scene)e.Node_AddChild(sword, trail)ColorStop
Section titled “ColorStop”ColorStop :: struct { // 0 (emitted) to 1 (dies) position: f32, // The color there color: sdl.Color,}A color at a point of a particle’s life: position 0 is when it’s emitted, 1 when it dies
struct. Source: particles.odin:60
ColorRamp
Section titled “ColorRamp”ColorRamp :: struct { // The stops; the first `count` are used stops: [MAX_COLOR_STOPS]ColorStop, // How many stops it has (an empty ramp is white) count: int,}Colors along a particle’s life, blended between the stops (kept sorted by position). Scene files
store it as position:#color pairs: "0:#ffe664 0.5:#e63228 1:#28282800".
struct. Source: particles.odin:71
ParticleShape
Section titled “ParticleShape”ParticleShape :: enum { // A circle of radius size.x Circle, // Radii size.x and size.y, turned by the particle's rotation Ellipse, // size.x by size.y, centered, turned by the particle's rotation Rectangle, // One screen pixel Pixel, // A line size.x long, scale.y thick, along the particle's rotation Line, // The emitter's texture, size.x by size.y, tinted by the particle's color Texture, // Drawn by the emitter's `customDraw` (a circle without one) Custom,}What a particle is drawn as
enum. Source: particles.odin:223
ParticleSettings
Section titled “ParticleSettings”ParticleSettings :: struct { // Emits from the start (otherwise ParticleEmitter_Start begins) emitting: bool `label:"Emitting" group:"Emission"`, // Starts a new cycle when one ends; otherwise stops after one continuous: bool `label:"Continuous"`, // Particles per cycle amount: int `min:"1" max:"500" label:"Amount"`, // Seconds a cycle lasts, and a particle lives lifetime: f32 `min:"0.01" max:"5" label:"Lifetime"`, // 0: particles are spread evenly over the cycle; 1: all emitted at once burst: f32 `min:"0" max:"1" label:"Burst"`, // Half-size of the area particles start in, around the emitter spread: [2]f32 `min:"0" max:"1280" label:"Spread"`, // Particles move with the emitter (its local space) instead of staying in the world localSpace: bool `label:"Local space"`, // Simulated and drawn on the graphics card (gpu_particles.odin: the GPU renderer; no // collisions), with `gpuAmount` particles; elsewhere on the CPU with `amount` gpu: bool `label:"On the GPU"`, // Particles per cycle on the GPU gpuAmount: int `min:"1" max:"200000" label:"GPU amount"`,
// What each particle is drawn as shape: ParticleShape `label:"Shape" group:"Shape"`, // A particle's size in pixels (what x and y mean depends on `shape`) size: [2]f32 `min:"0.01" max:"100" label:"Size"`, // How much of sizeSpread is used: 0 none, 1 all of it sizeVariance: f32 `min:"0" max:"1" label:"Size var."`, // Random change of each particle's size, up to this many pixels either way (per axis) sizeSpread: f32 `min:"0" max:"50" label:"Size spread"`, // Scale at birth, blended toward scaleEnd over the particle's life scaleStart: [2]f32 `min:"0" max:"1" label:"Scale start"`, // Scale at death scaleEnd: [2]f32 `min:"0" max:"1" label:"Scale end"`,
// Starting rotation of each particle rotation: f32 `min:"0" max:"359" label:"Rotation" group:"Rotation"`, // How much of rotationSpread is used: 0 none, 1 all of it rotationVariance: f32 `min:"0" max:"1" label:"Rotation var."`, // Random change of the starting rotation, up to this many degrees either way rotationSpread: f32 `min:"0" max:"359" label:"Rot. spread"`, // Spin, degrees per second torque: f32 `min:"-2000" max:"2000" label:"Torque"`, // How much of torqueSpread is used: 0 none, 1 all of it torqueVariance: f32 `min:"0" max:"1" label:"Torque var."`, // Random change of the spin, up to this many degrees per second either way torqueSpread: f32 `min:"0" max:"2000" label:"Torque spread"`, // How fast the spin changes, degrees per second² torqueAcceleration: f32 `min:"-2000" max:"2000" label:"Torque accel."`,
// Colors from colorRamp; otherwise from particleColor to colorEnd useColorRamp: bool `label:"Color ramp" group:"Color"`, // The colors over a particle's life (with useColorRamp) colorRamp: ColorRamp `label:"Ramp"`, // The color at birth (without useColorRamp) particleColor: sdl.Color `label:"Start color"`, // The color at death (without useColorRamp) colorEnd: sdl.Color `label:"End color"`, // Random change of each particle's red, green and blue colorVariance: f32 `min:"0" max:"1" label:"Color var."`,
// Direction particles are emitted in angle: f32 `min:"0" max:"359" label:"Angle" group:"Motion"`, // How much of angleSpread is used: 0 none, 1 all of it angleVariance: f32 `min:"0" max:"1" label:"Angle var."`, // Random change of the direction, up to this many degrees either way angleSpread: f32 `min:"0" max:"360" label:"Angle spread"`, // Starting speed, px/s velocity: f32 `min:"0" max:"2000" label:"Velocity"`, // How much of velocitySpread is used: 0 none, 1 all of it velocityVariance: f32 `min:"0" max:"1" label:"Velocity var."`, // Random change of the starting speed, up to this many px/s either way velocitySpread: f32 `min:"0" max:"2000" label:"Vel. spread"`, // Multiplies how far particles move each frame velocityScale: f32 `min:"0" max:"10" label:"Speed scale"`, // Speeds particles up (or down) along their emitted direction, px/s² acceleration: f32 `min:"-2000" max:"2000" label:"Acceleration"`,
// Gravity's direction (normalized when used; {0, 0} turns gravity off) gravityDirection: [2]f32 `min:"-1" max:"1" label:"Gravity dir." group:"Forces"`, // Gravity's strength, px/s² (negative pulls the other way) gravityVelocity: f32 `min:"-2000" max:"2000" label:"Gravity"`, // Pushes every particle, px/s² wind: [2]f32 `min:"-1000" max:"1000" label:"Wind"`,
// Particles bounce off each other and the edges of the view (see the top of particles.odin) collisionEnabled: bool `label:"Collide" group:"Collision"`, // Speed kept after a bounce elasticity: f32 `min:"0" max:"1" label:"Elasticity"`,}How an emitter emits and what its particles do. Pixels, seconds and degrees (clockwise).
Each field’s tags describe it for editors: min / max (the range a slider covers; code may go
outside it), label, and group on the first field of each group.
struct. Source: particles.odin:246
Particle
Section titled “Particle”Particle :: struct { // Pixels, in the world or the emitter's space position: [2]f32, velocity: [2]f32, // px/s², along its emitted direction acceleration: [2]f32, // Pixels, before scaling size: [2]f32, // Its scale at birth scaleStart: [2]f32, // Its scale at death scaleEnd: [2]f32, // Its scale now (drawn size: size × scale) scale: [2]f32, // Degrees, clockwise rotation: f32, // Its spin, degrees per second torque: f32, // How fast its spin changes, degrees per second² torqueAcceleration: f32, // Seconds it lives lifetime: f32, // Seconds it has lived age: f32, // The fraction of its life gone, 0 to 1 agePercent: f32, // Without a color ramp: its color at birth, blended toward colorEnd colorStart: sdl.Color, // Its color at death (without a color ramp) colorEnd: sdl.Color, // Random change of red, green and blue (colorVariance), kept for its whole life colorJitter: [3]f32, // Its color now color: sdl.Color, // In use; dead particles' slots are reused alive: bool,}One particle, in the emitter’s world or local space (ParticleSettings.localSpace)
struct. Source: particles.odin:359
ParticleEmitter
Section titled “ParticleEmitter”ParticleEmitter :: struct { // The node part: transform, hierarchy, hooks using node: Node, // How it emits and what its particles do settings: ParticleSettings, // Emitting now (`settings.emitting` is how it starts; a non-continuous emitter stops after a cycle) emitting: bool, // For the Texture shape texture: ^sdl.Texture, // For the Custom shape: draws one particle. The draw state is the particle's space, so the // Draw* helpers draw at it (origin at the particle, turned by its rotation; sizes aren't // scaled: use `particle.size * particle.scale`) customDraw: proc(emitter: ^ParticleEmitter, particle: ^Particle, renderer: ^sdl.Renderer), // MAX_PARTICLES slots, used as a ring (in the node's arena) particles: []Particle, // Seconds since the current cycle started cycleTime: f32, // Seconds toward the next emission emitTimer: f32, // Particles emitted in the current cycle emittedInCycle: int, // A cycle is under way (false: the next update starts one) cycleStarted: bool, // The slot the next particle goes in head: int, /* Notified once when a run has ended: emitting stopped (a one-shot cycle ended, or `ParticleEmitter_Stop`) and its last particle died. `source` is the emitter, no data. A continuous emitter that's never stopped never finishes; `ParticleEmitter_Start` begins another run, which notifies again when it ends. In the node's arena.
Example: // Given: scene: ^e.Scene, boom: ^e.ParticleEmitter e.Event_Subscribe(&boom.onFinished, proc(_: ^e.EventSubject, source: rawptr, _: e.EventData, userData: rawptr) { emitter := cast(^e.ParticleEmitter)source e.Scene_RemoveNode(emitter.scene, emitter.id) }, nil) */ onFinished: EventSubject `event:"A run ended: it stopped emitting and its last particle died"`, // The run stopped and onFinished is still to come (when the last particle dies) finishPending: bool, // On the GPU (`settings.gpu`: gpu_particles.odin; nil until then) gpu: ^GPUParticles,}A node that emits particles (see the top of particles.odin). Change settings at any time; new
particles use the new values, and live ones the forces and colors.
struct. Source: particles.odin:402
ParticleFieldInfo
Section titled “ParticleFieldInfo”ParticleFieldInfo :: struct { // The field's name, as scene files store it name: string, // The field's type (f32, int, bool, [2]f32, sdl.Color, ParticleShape, ColorRamp) type: typeid, // What editors show (the `label` tag; the name without one) label: string, // Set on the first field of each group group: string, // The slider range (when `ranged`) min, max: f32, // It has a `max` tag (a slider range) ranged: bool,}A ParticleSettings field, described by its tags (ParticleSettings_Fields)
struct. Source: particles.odin:641
GPUParticles
Section titled “GPUParticles”GPUParticles :: struct { // Seconds since the emitter was made (its own clock), when this run started and stopped clock, start, stopped: f64, // The emitter's path: (time, x, y, rotation), a ring ring: [GPU_PATH_RING][4]f32, ringHead, ringCount: int, // Drawn with the GPU last time (the CPU simulation is off then) active: bool, // The picture the particles are drawn into, as SDL's texture too; its renderer and size target: ^sdl.GPUTexture, targetTexture: ^sdl.Texture, renderer: ^sdl.Renderer, size: [2]i32, // The path's storage buffer and its upload buffer path: ^sdl.GPUBuffer, upload: ^sdl.GPUTransferBuffer, device: ^sdl.GPUDevice,}An emitter’s GPU state (ParticleEmitter.gpu, the node’s arena; SDL objects freed with the node)
struct. Source: gpu_particles.odin:36
GPUParticleResources
Section titled “GPUParticleResources”GPUParticleResources :: struct { device: ^sdl.GPUDevice, // Alpha (premultiplied) and additive blend, add: ^sdl.GPUGraphicsPipeline, sampler: ^sdl.GPUSampler, // A white pixel, for shapes without a texture white: ^sdl.GPUTexture, failed: bool,}The pipelines and helpers GPU particles share on a device (Game.gpuParticles)
struct. Source: gpu_particles.odin:56
LineJoint
Section titled “LineJoint”LineJoint :: enum { // Pointed (a miter), cut at LINE_MITER_LIMIT widths Sharp, // Rounded Round,}How a line’s corners are drawn
enum. Source: lines.odin:35
LineTextureMode
Section titled “LineTextureMode”LineTextureMode :: enum { // Once along the whole line Stretch, // Repeated every `width` pixels of length Tile,}How a line’s texture covers it
enum. Source: lines.odin:43
LineSettings
Section titled “LineSettings”LineSettings :: struct { // Thickness in pixels (a trail's at its newest point) width: f32, // A trail's thickness at its oldest point (lines: unused) endWidth: f32, // The color at the start (a trail's newest point) and at the end, blended along the length color, endColor: sdl.Color, // Corners and ends joint: LineJoint, roundCaps: bool, // A Line2D joins its last point to its first closed: bool, // How a texture (the node's `texture`) covers it textureMode: LineTextureMode, // Trail2D: seconds a point lasts; the distance the parent must move to add one; adding points lifetime: f32, minDistance: f32, emitting: bool,}A Line2D’s or Trail2D’s look (scene files’ attributes; a plain value)
struct. Source: lines.odin:51
Line2D
Section titled “Line2D”Line2D :: struct { using node: Node, settings: LineSettings, // The points, in the node's space (the node's arena) points: [dynamic][2]f32, // Drawn along it (nil: plain color) texture: ^sdl.Texture,}A line through points
struct. Source: lines.odin:78
Trail2D
Section titled “Trail2D”Trail2D :: struct { using node: Node, settings: LineSettings, // The points (world space), newest last, with the time each was added; the parent's position // now (the trail's head, drawn after the newest point) points: [dynamic]TrailPoint, head: [2]f32, // Seconds since it started (points' clock) clock: f32, texture: ^sdl.Texture,}A ribbon left behind its parent
struct. Source: lines.odin:88
TrailPoint
Section titled “TrailPoint”TrailPoint :: struct { position: [2]f32, time: f32,}One of a trail’s points
struct. Source: lines.odin:101
Procedures
Section titled “Procedures”ColorRamp_Evaluate
Section titled “ColorRamp_Evaluate”ColorRamp_Evaluate :: proc(ramp: ColorRamp, t: f32) -> sdl.ColorThe color of a ramp at a point of a particle’s life.
Inputs
- ramp: The ramp
- t: 0 (emitted) to 1 (dies); clamped
Returns
- The blended color (white for an empty ramp)
procedure. Source: particles.odin:98
ColorRamp_Sort
Section titled “ColorRamp_Sort”ColorRamp_Sort :: proc(ramp: ^ColorRamp, tracking: ^int = nil)Sorts a ramp’s stops by position.
Inputs
- ramp: The ramp
- tracking: Optional: a stop’s index, updated to where that stop ends up (an editor’s selection)
procedure. Source: particles.odin:122
ColorRamp_AddStop
Section titled “ColorRamp_AddStop”ColorRamp_AddStop :: proc(ramp: ^ColorRamp, position: f32, color: sdl.Color) -> intAdds a stop (kept sorted).
Inputs
- ramp: The ramp
- position: 0 (emitted) to 1 (dies); clamped
- color: The color there
Returns
- Its index, or -1 if the ramp is full (MAX_COLOR_STOPS)
procedure. Source: particles.odin:148
ColorRamp_RemoveStop
Section titled “ColorRamp_RemoveStop”ColorRamp_RemoveStop :: proc(ramp: ^ColorRamp, index: int) -> boolRemoves a stop. A ramp keeps at least two.
Inputs
- ramp: The ramp
- index: The stop’s index
Returns
- false if it wasn’t removed
procedure. Source: particles.odin:167
FormatColorRamp
Section titled “FormatColorRamp”FormatColorRamp :: proc(ramp: ColorRamp, allocator := context.allocator) -> stringFormats a ramp the way scene files store it: "0:#ffe664 0.5:#e63228 1:#28282800".
Inputs
- ramp: The ramp
- allocator: For the text
Returns
- The text (the caller frees it with
allocator)
procedure. Source: particles.odin:185
ParseColorRamp
Section titled “ParseColorRamp”ParseColorRamp :: proc(text: string) -> (ColorRamp, bool)Parses position:#color pairs separated by spaces (sorted afterwards; extra stops past
MAX_COLOR_STOPS are dropped).
Inputs
- text: The pairs, as
FormatColorRampwrites them
Returns
- The ramp, and false if a pair couldn’t be read (it’s skipped)
procedure. Source: particles.odin:204
CreateParticleEmitter
Section titled “CreateParticleEmitter”CreateParticleEmitter :: proc(scene: ^Scene, settings := DEFAULT_PARTICLE_SETTINGS) -> ^ParticleEmitterCreates a particle emitter.
Inputs
- scene: The scene
- settings: How it emits (DEFAULT_PARTICLE_SETTINGS unless given)
Returns
- The emitter; it starts emitting on the scene’s next update if
settings.emitting
procedure. Source: particles.odin:457
ParticleEmitter_Start
Section titled “ParticleEmitter_Start”ParticleEmitter_Start :: proc(emitter: ^ParticleEmitter)Starts emitting: a new cycle begins on the next update (live particles carry on). Use it to fire a one-shot (non-continuous) emitter again.
Inputs
- emitter: The emitter
Example
// Given: boom: ^e.ParticleEmitter, at: [2]f32boom.position = ate.ParticleEmitter_Start(boom)procedure. Source: particles.odin:483
ParticleEmitter_Stop
Section titled “ParticleEmitter_Stop”ParticleEmitter_Stop :: proc(emitter: ^ParticleEmitter)Stops emitting; live particles finish their lives, then onFinished is notified.
Inputs
- emitter: The emitter
procedure. Source: particles.odin:499
ParticleEmitter_Clear
Section titled “ParticleEmitter_Clear”ParticleEmitter_Clear :: proc(emitter: ^ParticleEmitter)Removes every live particle (emitting goes on if it was).
Inputs
- emitter: The emitter
procedure. Source: particles.odin:512
ParticleEmitter_AliveCount
Section titled “ParticleEmitter_AliveCount”ParticleEmitter_AliveCount :: proc(emitter: ^ParticleEmitter) -> intHow many particles are alive.
Inputs
- emitter: The emitter
Returns
- The count, at most MAX_PARTICLES
procedure. Source: particles.odin:525
ParticleSettings_Fields
Section titled “ParticleSettings_Fields”ParticleSettings_Fields :: proc() -> []ParticleFieldInfoThe settings’ fields, for editors: name, type and the tags (min, max, label, group).
Temp allocated.
procedure. Source: particles.odin:622
ParticleSettings_Get
Section titled “ParticleSettings_Get”ParticleSettings_Get :: proc(settings: ParticleSettings, name: string) -> (string, bool)A setting’s value as scene files store it (numbers, true/false, “x,y”, #rrggbb[aa], enum
names, a ramp’s position:#color pairs).
Inputs
- settings: The settings
- name: The field’s name (
ParticleSettings_Fields)
Returns
- The text (temp allocated), and false for an unknown name
procedure. Source: particles.odin:667
ParticleSettings_Set
Section titled “ParticleSettings_Set”ParticleSettings_Set :: proc(settings: ^ParticleSettings, name, text: string) -> boolSets a setting from text (the format of ParticleSettings_Get).
Inputs
- settings: The settings to change
- name: The field’s name
- text: Its value (surrounding spaces are ignored)
Returns
- false if the name is unknown or the text isn’t a value for it (nothing changes)
Example
// Given: emitter: ^e.ParticleEmittere.ParticleSettings_Set(&emitter.settings, "particleColor", "#ff8800")e.ParticleSettings_Set(&emitter.settings, "spread", "16,4")procedure. Source: particles.odin:699
FormatParticleSettings
Section titled “FormatParticleSettings”FormatParticleSettings :: proc(settings: ParticleSettings) -> []ScriptPropDataThe settings that differ from DEFAULT_PARTICLE_SETTINGS, as name/value text in field order: the
attributes of a scene file’s <particles> element.
Inputs
- settings: The settings
Returns
- The pairs (temp allocated)
procedure. Source: particles.odin:746
ParticleEmitter_OnGPU
Section titled “ParticleEmitter_OnGPU”ParticleEmitter_OnGPU :: proc(emitter: ^ParticleEmitter) -> boolWhether an emitter is drawing on the GPU now
procedure. Source: gpu_particles.odin:80
CreateLine2D
Section titled “CreateLine2D”CreateLine2D :: proc(scene: ^Scene, points: [][2]f32 = nil, settings := DEFAULT_LINE_SETTINGS) -> ^Line2DCreates a Line2D and adds it to the scene (at the start of the next update).
Inputs
- scene: The scene
- points: Its points, in its own space (copied)
- settings: Its look
Returns
- The line
procedure. Source: lines.odin:117
Line2D_SetPoints
Section titled “Line2D_SetPoints”Line2D_SetPoints :: proc(line: ^Line2D, points: [][2]f32)Replaces a line’s points (copied)
procedure. Source: lines.odin:138
Line2D_AddPoint
Section titled “Line2D_AddPoint”Line2D_AddPoint :: proc(line: ^Line2D, point: [2]f32)Adds a point at the end of a line
procedure. Source: lines.odin:144
Line2D_Clear
Section titled “Line2D_Clear”Line2D_Clear :: proc(line: ^Line2D)Removes a line’s points
procedure. Source: lines.odin:149
CreateTrail2D
Section titled “CreateTrail2D”CreateTrail2D :: proc(scene: ^Scene, settings := DEFAULT_LINE_SETTINGS) -> ^Trail2DCreates a Trail2D and adds it to the scene (at the start of the next update). Make it a child of what leaves the trail.
Inputs
- scene: The scene
- settings: Its look and how long points last
Returns
- The trail
procedure. Source: lines.odin:164
Trail2D_Clear
Section titled “Trail2D_Clear”Trail2D_Clear :: proc(trail: ^Trail2D)Forgets a trail’s points (after a teleport: no streak across the screen)
procedure. Source: lines.odin:174
Trail2D_SetEmitting
Section titled “Trail2D_SetEmitting”Trail2D_SetEmitting :: proc(trail: ^Trail2D, emitting: bool)Starts or stops adding points (stopped, the trail fades away as its points age)
procedure. Source: lines.odin:179
Line_Geometry
Section titled “Line_Geometry”Line_Geometry :: proc(points: [][2]f32, widths: []f32, colors: []sdl.FColor, us: []f32, joint: LineJoint, roundCaps, closed: bool, vertices: ^[dynamic]sdl.Vertex, indices: ^[dynamic]c.int)A thick polyline’s triangles: points in screen space, each with its width and color, and its
u along the line (texture coordinates). Closed lines join the last point to the first.
Inputs
- points, widths, colors, us: Per point (same length)
- joint, roundCaps, closed: The look
- vertices, indices: Appended to
procedure. Source: lines.odin:192
Constants and variables
Section titled “Constants and variables”MAX_COLOR_STOPS
Section titled “MAX_COLOR_STOPS”MAX_COLOR_STOPS :: 8Most colors a ColorRamp holds
constant. Source: particles.odin:55
MAX_PARTICLES
Section titled “MAX_PARTICLES”MAX_PARTICLES :: 1000Most particles an emitter has alive at once; the oldest are reused past it
constant. Source: particles.odin:57
DEFAULT_COLOR_RAMP
Section titled “DEFAULT_COLOR_RAMP”DEFAULT_COLOR_RAMP :: ColorRamp{ stops = { 0 = {0, {255, 230, 100, 255}}, 1 = {0.5, {230, 50, 40, 255}}, 2 = {1, {40, 40, 40, 0}}, }, count = 3,}Warm yellow when emitted, fiery red at mid-life, fading out at the end
constant. Source: particles.odin:79
DEFAULT_PARTICLE_SETTINGS
Section titled “DEFAULT_PARTICLE_SETTINGS”DEFAULT_PARTICLE_SETTINGS :: ParticleSettings{ emitting = true, continuous = true, amount = 50, gpuAmount = 5000, lifetime = 2, shape = .Circle, size = {5, 5}, scaleStart = {1, 1}, scaleEnd = {1, 1}, useColorRamp = true, colorRamp = DEFAULT_COLOR_RAMP, particleColor = {255, 255, 255, 255}, colorEnd = {255, 255, 255, 255}, velocity = 100, velocityScale = 1, gravityDirection = {0, 1}, gravityVelocity = 200, elasticity = 0.7,}The settings of a new emitter, and of attributes a scene file leaves out
constant. Source: particles.odin:337
MAX_GPU_PARTICLES
Section titled “MAX_GPU_PARTICLES”MAX_GPU_PARTICLES :: 200000The most particles an emitter simulates on the GPU
constant. Source: gpu_particles.odin:28
GPU_PATH_SAMPLES
Section titled “GPU_PATH_SAMPLES”GPU_PATH_SAMPLES :: 128How many samples of the emitter’s path the shader reads
constant. Source: gpu_particles.odin:30
DEFAULT_LINE_SETTINGS
Section titled “DEFAULT_LINE_SETTINGS”DEFAULT_LINE_SETTINGS :: LineSettings{width = 4, endWidth = 0, color = {255, 255, 255, 255}, endColor = {255, 255, 255, 255}, lifetime = 0.4, minDistance = 4, emitting = true}A line’s defaults (a trail’s too)
constant. Source: lines.odin:72
LINE_MITER_LIMIT
Section titled “LINE_MITER_LIMIT”LINE_MITER_LIMIT :: 2How far a sharp corner may stick out, in widths (sharper corners are cut flat)
constant. Source: lines.odin:75
