luv

Workshop wiki

balls.lisp

luvcraft/balls.lisp

system luvcraft/core · 70 definitions · on GitHub

The things with weight: what the block world does with its physics.

PHYSICS.LISP simulates spheres and knows nothing about the game; this is the game's side of that seam. It decides what a body looks like (a kind: a colour, a pattern, a glow, a size, a bounce), draws every body as a true ray-traced sphere -- one instance record per body for the sphere pipeline's camera-facing quads, patterned and lit in the shader (LUVCRAFT/SHADERS.LISP, role :PHYSICS-SPHERE) -- while the shadow pass keeps rasterizing each body as a small turning cube, posts the player and the animals into the step as kinematic boxes so a ball rolls off a turtle and a walking player kicks what is in the way, and gives the world these ways to make bodies:

  • the ball, a hand item (B takes it out): left click throws one, right

click drops a whole handful; balls bounce, roll, pile up, and sleep;

balls, smiley balls, and classic balls around a point;

  • the FOUNTAIN block, which sprays drops of water that fall through

one another and splash out on whatever they land on;

  • the LAVA SPRING block, which spits slow glowing gobbets that stick

where they land, cool, and go out.

The events the step reports come back here too: a hit on a box owned by an animal startles it (critter-struck), and the step's own facts -- how many bodies are awake, how long it took -- are read off the world for the metabar's knobs.

in-package#:luvcraft

--------------------------------------------------------------------- Three tiles of the atlas: what a ball, a drop, and a gobbet are painted with.

defconstant+ball-tile+:ball
defconstant+water-drop-tile+:water
defconstant+lava-tile+:lava
defmethodpaint-block-atlas-tile
tile
eql:ball
xy

A ball: worn red rubber with one pale band around it, so it is seen to turn.

let*
seam
<=6y8
variation
ifseam
shaded-block-atlas-pixel226214190variation
shaded-block-atlas-pixel1966248variation
defmethodpaint-block-atlas-tile
tile
eql:water
xy

Water: a clear cool blue with a lighter ripple through it.

let
ripple
shaded-block-atlas-pixel78140214
round
-ripple128
5
defmethodpaint-block-atlas-tile
tile
eql:lava
xy

Lava: near-white heat veined through orange; the glow is added per body.

let
if
>vein175
shaded-block-atlas-pixel2409624
round
-vein128
6

--------------------------------------------------------------------- Body kinds: the game's palette of things a body can be. The physics keeps only the index; everything the eye or the game wants is here. The albedo and pattern feed the sphere pipeline's instance stream, so this vector stays the single source of truth for what a kind looks like; the tile survives for the hand item and the atlas painters.

defunbody-pattern-index
pattern

The sphere fragment stage's number for a surface pattern.

The shader selects the procedural pattern by this lane, so the pairing is closed on both sides: a new pattern is a new shader arm and a new entry here, together.

ecasepattern
:plain0f0
:banded1f0
:marble2f0
:beach3f0
:smiley4f0
defstruct
body-kind
:constructormake-body-kind
nametile&key
emission0.0
radius0.22
mass1.0
restitution0.5
friction0.5
rolling-resistance0.01
damping0.05
collides-pt
lifetimenil
hit-report-pnil
draw-scale1.0
albedo'
0.80.80.8
pattern:plain
&aux
albedo-red
float
firstalbedo
0f0
albedo-green
float
secondalbedo
0f0
albedo-blue
float
thirdalbedo
0f0
pattern-index
name:ball:typekeyword
tile:ball:typekeyword
emission0.0:typesingle-float
radius0.22:typesingle-float
mass1.0:typesingle-float
restitution0.5:typesingle-float
friction0.5:typesingle-float
rolling-resistance0.01:typesingle-float
damping0.05:typesingle-float
collides-pt
lifetimenil
hit-report-pnil

The drawn sphere's radius as a fraction of the physics radius. One is the honest size; the constructor keeps the knob for a kind that wants to read smaller than it collides.

draw-scale1.0:typesingle-float

The base colour the shader patterns over, resolved here so *BODY-KINDS* stays the palette's one authority.

albedo-red0.8:typesingle-float
albedo-green0.8:typesingle-float
albedo-blue0.8:typesingle-float
pattern:plain:typekeyword
pattern-index0.0:typesingle-float
defparameter*body-kinds*
vector
make-body-kind:ball+ball-tile+:radius0.22:mass1.0:restitution0.55:friction0.6:rolling-resistance0.015:damping0.08:hit-report-pt:albedo'
0.770.240.19
:pattern:banded
make-body-kind:marble+ball-tile+:radius0.12:mass0.3:restitution0.4:friction0.5:rolling-resistance0.01:damping0.05:albedo'
0.620.720.82
:pattern:marble
make-body-kind:water-drop+water-drop-tile+:radius0.07:mass0.05:restitution0.15:friction0.2:rolling-resistance0.05:damping0.4:collides-pnil:lifetime2.6:albedo'
0.310.550.84
make-body-kind:lava-gobbet+lava-tile+:emission1.5:radius0.14:mass0.6:restitution0.0:friction1.0:rolling-resistance0.4:damping1.2:collides-pt:lifetime7.0:albedo'
0.940.380.09

The party kinds. The beach ball is big, light, and bouncy; the smiley ball is small, bouncier still, and wears its face in the pattern frame, so the grin tumbles as it bounces.

make-body-kind:beach-ball+ball-tile+:radius0.45:mass0.4:restitution0.8:friction0.5:rolling-resistance0.008:damping0.06:hit-report-pt:albedo'
0.970.950.92
:pattern:beach
make-body-kind:smiley-ball+ball-tile+:radius0.2:mass0.5:restitution0.9:friction0.55:rolling-resistance0.012:damping0.06:hit-report-pt:albedo'
0.990.800.16
:pattern:smiley
"The kinds a body may be, by index; the physics stores the index."
defunbody-kind-index
name
or
positionname*body-kinds*:key#'body-kind-name
error"There is no body kind named ~S."name
defunspawn-body-of-kind
physicsnamexyz&key
vx0.0
vy0.0
vz0.0
lifetime

Add a body of the kind name to physics and return its handle.

let*
kind
aref*body-kinds*index
spawn-physics-bodyphysicsxyz:radius
body-kind-radiuskind
:mass
body-kind-masskind
:vxvx:vyvy:vzvz:restitution
body-kind-restitutionkind
:friction
body-kind-frictionkind
:rolling-resistance
body-kind-rolling-resistancekind
:damping
body-kind-dampingkind
:kindindex:collides-with-bodies-p
body-kind-collides-pkind
:hit-report-p
body-kind-hit-report-pkind
:lifetime
orlifetime
body-kind-lifetimekind

--------------------------------------------------------------------- Drawing. The scene pass gets one 16-float instance record per body -- centre and radius, orientation quaternion, albedo and emission, sampled light and pattern -- for the sphere pipeline's camera-facing quads; the shadow pass still rasterizes each body as a small turning cube in the block pipeline's vertex format, which is cheap and correct for a depth map. Both streams are preallocated specialized arrays owned by one streams record in the session; displaced views of the filled parts are what the frame uploads. Because the sphere quads blend without writing depth, the instance records are handed over farthest-from-the-eye first, so a pile of balls occludes itself correctly.

defconstant+physics-render-body-limit+2000"The most bodies drawn in one frame; both streams are sized for it."
defconstant+physics-vertices-per-body+36"Cube vertices per body in the shadow stream."
defconstant+physics-instance-floats-per-body+16"Four vec4 lanes per body in the sphere instance stream."
defconstant+physics-shadow-cube-scale+0.78

The shadow cube's half-size as a fraction of the drawn sphere's radius: a touch under, toward the inscribed cube, so shadows do not read fat.

defparameter*physics-cube-template*nil

Thirty-six vertices of a unit cube about the origin: for each, the local corner (-0.5..0.5), the tile-local UV, and the face normal, flat.

defunphysics-cube-template
or*physics-cube-template*
setf*physics-cube-template*
let
template
make-array
*368
:element-type'single-float
index0
dolist
let*
normal
block-face-neighborface
corners
block-face-cornersface
dolist
corner-index'
012023
let
corner
nthcorner-indexcorners
multiple-value-bind
uv
setf
areftemplate
+index0
-
float
firstcorner
0f0
0.5f0
areftemplate
+index1
-
float
secondcorner
0f0
0.5f0
areftemplate
+index2
-
float
thirdcorner
0f0
0.5f0
areftemplate
+index3
floatu0f0
areftemplate
+index4
floatv0f0
areftemplate
+index5
float
voxel-direction-dxnormal
0f0
areftemplate
+index6
float
voxel-direction-dynormal
0f0
areftemplate
+index7
float
voxel-direction-dznormal
0f0
incfindex8
template
defstruct
physics-body-streams
:constructormake-physics-body-streams

The per-frame render products built from the physics columns.

INSTANCES holds the sphere records the scene pass draws, already ordered farthest first for the blend; SCRATCH holds them in storage order before the sort, with DEPTHS and ORDER as the sort's reusable working set. SHADOW-VERTICES holds the little cubes the shadow pass rasterizes, whose order no depth map cares about.

instances
make-array:element-type'single-float:initial-element0f0
:type
simple-arraysingle-float
scratch
make-array:element-type'single-float:initial-element0f0
:type
simple-arraysingle-float
depths
make-array+physics-render-body-limit+:element-type'single-float:initial-element0f0
:type
simple-arraysingle-float
order
make-array+physics-render-body-limit+:element-type'fixnum:initial-element0
:type
simple-arrayfixnum
shadow-vertices:type
simple-arraysingle-float
defunensure-physics-body-streams
session

The session's PHYSICS-VERTEX-STREAM slot holds the whole streams record; its PHYSICS-VERTEX-COUNT slot holds the drawn body count.

or
luvcraft-session-physics-vertex-streamsession
setf
luvcraft-session-physics-vertex-streamsession
make-physics-body-streams
defunphysics-body-light-levels
worldxyz

Normalized sky and block light at a body's centre; open sky when absent.

multiple-value-bind
skyblockstatus
if
eqstatus:resident
values
/sky15f0
/block15f0
values1f00f0
defunbuild-physics-body-streams
physicsworldstreamseye-xeye-yeye-z

Fill streams from physics's bodies and return how many were drawn.

One pass writes each body's sphere instance record into the scratch stream in storage order, its squared distance to the eye beside it, and its shadow cube's corners -- position lanes only; the shadow stage reads nothing else. The instance records are then dealt into the upload stream farthest first, because the scene pass blends them over each other without writing depth.

declare
typephysics-body-streamsstreams
single-floateye-xeye-yeye-z
optimize
speed3
safety1
let*
scratch
physics-body-streams-scratchstreams
instances
physics-body-streams-instancesstreams
depths
physics-body-streams-depthsstreams
order
physics-body-streams-orderstreams
shadow
physics-body-streams-shadow-verticesstreams
drawn0
declare
type
simple-arraysingle-float
templatescratchinstancesdepthsshadow
type
simple-arrayfixnum
order
typesimple-vectorkinds
fixnumdrawnlimit
dolist
columns
list
physics-world-awakephysics
physics-world-sleepingphysics
records:with-columnar-buffer-storage
countrow
xsx
ysy
zsz
radiiradius
qxsqx
qysqy
qzsqz
qwsqw
kind-indiceskind
columnsphysics-body-columns
declare
ignorerow
dotimes
icount
when
>=drawnlimit
let*
kind
arefkinds
arefkind-indicesi
cx
arefxsi
cy
arefysi
cz
arefzsi
drawn-radius
*
arefradiii
body-kind-draw-scalekind
emission
body-kind-emissionkind
qx
arefqxsi
qy
arefqysi
qz
arefqzsi
qw
arefqwsi

The rotation matrix of the unit quaternion, for the shadow cube's turned corners.

xx
*qxqx
yy
*qyqy
zz
*qzqz
xy
*qxqy
xz
*qxqz
yz
*qyqz
wx
*qwqx
wy
*qwqy
wz
*qwqz
m00
-1f0
*2f0
+yyzz
m01
*2f0
-xywz
m02
*2f0
+xzwy
m10
*2f0
+xywz
m11
-1f0
*2f0
+xxzz
m12
*2f0
-yzwx
m20
*2f0
-xzwy
m21
*2f0
+yzwx
m22
-1f0
*2f0
+xxyy
dx
-cxeye-x
dy
-cyeye-y
dz
-czeye-z
declare
typebody-kindkind
single-floatcxcyczdrawn-radiusemissionqxqyqzqwxxyyzzxyxzyzwxwywzm00m01m02m10m11m12m20m21m22scaledxdydz
fixnumoutshadow-out
multiple-value-bind
sky-levelblock-level
declare
single-floatsky-levelblock-level
setf
arefscratch
+out0
cx
arefscratch
+out1
cy
arefscratch
+out2
cz
arefscratch
+out3
drawn-radius
arefscratch
+out4
qx
arefscratch
+out5
qy
arefscratch
+out6
qz
arefscratch
+out7
qw
arefscratch
+out8
body-kind-albedo-redkind
arefscratch
+out9
body-kind-albedo-greenkind
arefscratch
+out10
body-kind-albedo-bluekind
arefscratch
+out11
emission
arefscratch
+out12
sky-level
arefscratch
+out13
block-level
arefscratch
+out14
body-kind-pattern-indexkind
arefscratch
+out15
0f0
arefdepthsdrawn
+
*dxdx
+
*dydy
*dzdz
dotimes
let*
t0
*v8
lx
*scale
areftemplatet0
ly
*scale
areftemplate
+t01
lz
*scale
areftemplate
+t02
declare
fixnumt0
single-floatlxlylz
setf
arefshadow
+shadow-out0
+cx
*m00lx
*m01ly
*m02lz
arefshadow
+shadow-out1
+cy
*m10lx
*m11ly
*m12lz
arefshadow
+shadow-out2
+cz
*m20lx
*m21ly
*m22lz
incfdrawn

Farthest first for the blend. The displaced view is one small header per frame; SBCL sorts vectors in place.

dotimes
idrawn
setf
areforderi
i
when
>drawn1
sort
make-arraydrawn:element-type'fixnum:displaced-toorder
lambda
ab
>
arefdepthsa
arefdepthsb
dotimes
slotdrawn
let
declare
fixnumsourcetarget
dotimes
setf
arefinstances
+targetlane
arefscratch
+sourcelane
drawn
defunluvcraft-physics-body-count
session

How many bodies the last build of the session's streams drew.

luvcraft-session-physics-vertex-countsession
defunluvcraft-physics-instance-stream
session

The filled sphere instance records, farthest first, for the upload.

make-array
*
luvcraft-session-physics-vertex-countsession
+physics-instance-floats-per-body+
:element-type'single-float:displaced-to
physics-body-streams-instances
defunluvcraft-physics-shadow-vertex-count
session

How many cube vertices the shadow pass draws for the bodies.

*
luvcraft-session-physics-vertex-countsession
+physics-vertices-per-body+
defunluvcraft-physics-shadow-stream
session

The filled part of the shadow cube stream, for the upload.

make-array:element-type'single-float:displaced-to
physics-body-streams-shadow-vertices

--------------------------------------------------------------------- The session's physics: made on first use, stepped at a fixed rate from the frame clock, fed the player and the animals as boxes, and asked afterwards what happened.

defparameter*physics-step-seconds*
/1d060d0
"The fixed step the session's physics advances by; four substeps inside."
defparameter*physics-max-steps-per-frame*3

How many steps one frame may catch up; beyond that time is dropped, so a stall does not become a spiral.

defunensure-luvcraft-physics
session
or
luvcraft-session-physicssession
let
physics
make-physics-world:terrain
luvcraft-session-worldsession
setf
physics-world-step-secondsphysics
coerce*physics-step-seconds*'single-float
luvcraft-session-physicssession
physics
physics
defunpost-luvcraft-kinematic-boxes
sessionphysics

Tell physics where the player and the animals are and how they move.

let
player
luvcraft-session-playersession
whenplayer
let
x
player-xplayer
y
player-yplayer
z
player-zplayer
post-physics-boxphysics
-xhalf
y
-zhalf
+xhalf
+zhalf
:vx:vy:vz:ownerplayer
physics
defgenericcritter-struck
critterxyzspeed
:documentation

Something hit critter at X,Y,Z arriving at speed. Most animals ignore it; a turtle takes it as a reason to go somewhere else.

defmethodcritter-struck
critterxyzspeed
declare
ignorecritterxyzspeed
nil
defmethodcritter-struck
xyzspeed
declare
ignorexyz
when
>speed2.5
setf
turtle-resting-pturtle
nil
turtle-mood-secondsturtle
3d0
defunhandle-luvcraft-physics-events
sessionphysics

Act on what the step found out.

declare
ignoresession
do-physics-events
kindhandle-ahandle-bownerxyzspeedphysics
when
and
eqkind:hit
typepowner'critter
critter-struckownerxyzspeed
defunadvance-luvcraft-physics
sessionseconds

Step the session's physics as many fixed steps as seconds owe, then build this frame's sphere instance and shadow cube streams.

let
incf
luvcraft-session-physics-clocksession
seconds
let
steps0
loopwhile
and
>=
luvcraft-session-physics-clocksession
*physics-step-seconds*
do
decf
luvcraft-session-physics-clocksession
*physics-step-seconds*
incfsteps

A frame that fell far behind forgets the rest rather than catching up forever.

when
>=
luvcraft-session-physics-clocksession
*physics-step-seconds*
setf
luvcraft-session-physics-clocksession
0d0
let
eye
camera-position
luvcraft-session-camerasession
setf
luvcraft-session-physics-vertex-countsession
build-physics-body-streamsphysics
luvcraft-session-worldsession
coerce
vec3-xeye
'single-float
coerce
vec3-yeye
'single-float
coerce
vec3-zeye
'single-float
physics

--------------------------------------------------------------------- Springs: the fountain and the lava well. A spring is a coordinate the session found in its world's authored edits, or was told about when the player placed one; each physics step it may throw something, if its cell is resident and still holds a spring.

defstruct
luvcraft-spring
:constructormake-luvcraft-spring
xyzkind
x0:typefixnum
y0:typefixnum
z0:typefixnum
kind:fountain:typekeyword
count0:typefixnum
defunworld-spring-coordinates
world

The (X Y Z KIND) of every spring block written into world's edits.

let
source
block-world-sourceworld
when
loopforcoordinatebeingthehash-keysof
block-edit-overlay-entries
little-world-source-editssource
using
hash-valueblock
whencollect
destructuring-bind
xyz
coordinate
make-luvcraft-springxyz
block-kind-nameblock
defunfind-luvcraft-springs
session

Rediscover the world's springs from its authored edits.

setf
luvcraft-session-springssession
world-spring-coordinates
luvcraft-session-worldsession
defmethodluvcraft-block-placed
sessionxyz
push
make-luvcraft-springxyz
block-kind-nameblock
luvcraft-session-springssession
defmethodluvcraft-block-removed
sessionxyz
setf
luvcraft-session-springssession
remove-if
lambda
spring
and
=x
luvcraft-spring-xspring
=y
luvcraft-spring-yspring
=z
luvcraft-spring-zspring
luvcraft-session-springssession
defunspring-noise
springsalt

A stable 0..1 reading for spring's current throw and salt.

critter-noise
+
*7919
luvcraft-spring-xspring
*104729
luvcraft-spring-yspring
*1299709
luvcraft-spring-zspring
luvcraft-spring-countspring
salt
defparameter*lava-gobbet-period*6"A lava spring spits one gobbet every this many steps."
defunspray-luvcraft-spring
springsessionphysics
let
x
luvcraft-spring-xspring
y
luvcraft-spring-yspring
z
luvcraft-spring-zspring
multiple-value-bind
blockstatus
world-block-at
luvcraft-session-worldsession
xyz
when
and
eqstatus:resident
ecase
luvcraft-spring-kindspring
:fountain
dotimes
incf
luvcraft-spring-countspring
let*
angle
*2d0pi
spread
*1.6d0
up
+9.5d0
*2.5d0
spawn-body-of-kindphysics:water-drop
+x0.5d0
*0.12d0
+y1.1d0
+z0.5d0
*0.12d0
:vx
*spread
:vyup:vz
*spread
:lava-spring
incf
luvcraft-spring-countspring
when
zerop
mod
luvcraft-spring-countspring
*lava-gobbet-period*
let*
angle
*2d0pi
spread
+0.4d0
*1.4d0
up
+5.0d0
*3.0d0
spawn-body-of-kindphysics:lava-gobbet
+x0.5d0
+y1.2d0
+z0.5d0
:vx
*spread
:vyup:vz
*spread
defunspray-luvcraft-springs
sessionphysics
dolist
spring
luvcraft-session-springssession
spray-luvcraft-springspringsessionphysics

--------------------------------------------------------------------- The ball in the hand.

defparameter*ball-throw-speed*14.0d0"How fast a thrown ball leaves the hand, cells per second."
defclassball
thrown:initform0:accessorball-thrown-count:documentation"How many balls this hand has thrown."
:documentation

A ball to throw. The hand never runs out: each throw is a new body.

defmethodhand-item-name
itemball

ball

defmethodhand-item-carry-pose
itemball
body
declare
ignorebody

Held low and to the right, a little forward, the way you carry a ball you mean to throw.

'
0.26d0-0.40d00.66d00.15d0-0.10d00.0d0
defmethodmap-hand-item-boxes
itemball
bodyfunction
declare
ignorebody

Small in the hand: the grip frame sits close to the eye.

let
half0.055d0
funcallfunction0d0half0d0halfhalfhalf+ball-tile+:stretch-pt
defunthrow-luvcraft-ball
session&key
kind:ball
aim-right0d0
aim-up0d0

Throw a body of kind from the player's eye along the view, nudged by aim-right and aim-up; return its handle.

let*
camera
luvcraft-session-camerasession
player
luvcraft-session-playersession
position
camera-positioncamera
multiple-value-bind
rightupforward
let*
sxaim-right
syaim-up
dx
+
vec3-xforward
*sx
vec3-xright
*sy
vec3-xup
dy
+
vec3-yforward
*sx
vec3-yright
*sy
vec3-yup
dz
+
vec3-zforward
*sx
vec3-zright
*sy
vec3-zup
length
sqrt
+
*dxdx
*dydy
*dzdz
start-distance0.7d0
spawn-body-of-kindphysicskind
+
vec3-xposition
*start-distancedx
*0.25d0
vec3-xright
+
vec3-yposition
*start-distancedy
-0.15d0
+
vec3-zposition
*start-distancedz
*0.25d0
vec3-zright
:vx
+
*speeddx
ifplayer0d0
:vy
+
*speeddy
ifplayer0d0
:vz
+
*speeddz
ifplayer0d0
defmethodhand-item-use
itemball
bodysessionbutton
declare
ignorebody
casebutton
:left
incf
ball-thrown-countitem

Every fifth ball out of the hand is a smiley: enough to be a delight, not so many that the ball stops being the ball.

throw-luvcraft-ballsession:kind
if
zerop
mod
ball-thrown-countitem
5
:smiley-ball:ball
t
:right

A handful of marbles, scattered the same way from the same count.

dotimes
i12
incf
ball-thrown-countitem
throw-luvcraft-ballsession:kind:marble:speed9d0:aim-right
*0.5d0
-
critter-noise4242
ball-thrown-countitem
1
0.5d0
:aim-up
*0.5d0
-
critter-noise4242
ball-thrown-countitem
2
0.5d0
t
tnil
defuntoggle-luvcraft-ball
session

Take the session's ball out, or put it away.

toggle-hand-item
luvcraft-session-bodysession
session'ball

--------------------------------------------------------------------- The party: a burst of balls for a birthday.

defparameter*party-ball-kinds*
:beach-ball:smiley-ball:ball:smiley-ball
"The rotation SCATTER-PARTY-BALLS deals from, in order."
defunscatter-party-balls
session&keycenter
count20

Scatter a deterministic mix of beach balls, smiley balls, and classic balls around center, each with a small pop-up velocity, and return their handles, newest first.

center is an (X Y Z) list; without one the balls burst a few cells ahead of the session's camera. The scatter is hashed, not random, so the same call throws the same party.

let*
center
orcenter
let
camera
luvcraft-session-camerasession
multiple-value-bind
rightupforward
declare
ignorerightup
let
eye
camera-positioncamera
list
+
vec3-xeye
*4d0
vec3-xforward
+
vec3-yeye
*4d0
vec3-yforward
+
vec3-zeye
*4d0
vec3-zforward
handles'
destructuring-bind
xyz
center
dotimes
icount
let*
reach
lift
+0.6d0
*1.4d0
up
+2.0d0
*3.0d0
spread
+0.5d0
*1.5d0
push
spawn-body-of-kindphysicskind
+ylift
:vx
*spread
:vyup:vz
*spread
handles
handles

--------------------------------------------------------------------- The knobs: what the metabar can turn on the physics.

defun
magnitude
setf*physics-gravity*
-
coercemagnitude'single-float
magnitude
defunball-bounciness
body-kind-restitution
defun
setf
body-kind-restitution
coercebounciness'single-float
bounciness
define-knobphysics-gravity
:group:physics:label"weight of things":quantity
:quantity:gravity-magnitude:unit
:cell1
:second-2
:minimum0.0:maximum60.0:step1.0
define-knobball-bounce
:group:physics:label"bounce of a ball":quantity
:quantity:bounciness:unit:one
:minimum0.0:maximum1.0:step0.05
define-knobfountain-rate
:group:physics:label"drops per step":quantity
:quantity:body-count:unit:one
:typeinteger:minimum0:maximum8:step1
*fountain-drops-per-step*
define-knobphysics-substeps
:group:physics:quantity
:quantity:substep-count:unit:one
:typeinteger:minimum1:maximum8:step1
*physics-substeps*

--------------------------------------------------------------------- Reading the physics from the metabar.

defunluvcraft-physics-awake-count
session
let
physics
luvcraft-session-physicssession
ifphysics
physics-body-columns-length
physics-world-awakephysics
0
defunluvcraft-physics-asleep-count
session
let
physics
luvcraft-session-physicssession
ifphysics
physics-body-columns-length
physics-world-sleepingphysics
0
defunluvcraft-physics-step-milliseconds
session
let
physics
luvcraft-session-physicssession
ifphysics
*1000d0
physics-world-last-step-real-secondsphysics
0d0
defunluvcraft-physics-contact-count
session
let
physics
luvcraft-session-physicssession
ifphysics
physics-world-last-step-contact-countphysics
0
defunclear-luvcraft-physics-bodies
session

Remove every ball, drop, and gobbet from the session's world.

let
physics
luvcraft-session-physicssession
whenphysics
session