NAME
Physics::Balls::World - a surface, its walls, noses and gates, and the constants
VERSION
Version 0.06
SYNOPSIS
my $world = Physics::Balls::World->from_table($table,
mu => { s => 0.2, r => 0.015, sp => 0.044 },
e => { bb => 0.95, c => 0.8, cf => 0.2, rc => 0.7 },
vmax => 8,
);
# or straight from geometry you built yourself, in metres
my $world = Physics::Balls::World->new(L => 2.54, W => 1.27, R => 0.028575,
walls => \@walls, noses => \@noses, gates => \@gates);
# a surface whose balls curve: a green, with a jack and a bowl on each hand
my $green = Physics::Balls::World->new(L => 9, W => 41, R => 0.0655,
walls => \@box, noses => [], gates => \@ditches,
mu => { s => 0.2, r => 0.0281, sp => 0.044 },
curve => { k => 0.07, vref => 1, vmin => 0.25, p => 2, kmax => 0.6, cap => 0.002, vfrac => 0.1 },
kinds => [ { curve => 0 }, { curve => 1 }, { curve => -1 } ],
);
DESCRIPTION
Everything the engine needs to know before a strike. A world is built once and shared between shots; the C engine behind it is created on the first strike and freed with the world.
The curve
A ball of a kind whose curve is not zero does not run straight. Its path is a chain of parabolas that bends: at each of many small steps the engine rotates the ball's velocity and its roll together through a small angle and starts the next parabola, so every segment a client plays back is still a segment and the turn adds no energy. The turn rate is
k_per_second = k * curve * (vref / max(|v|, vmin)) ^ p
clamped to kmax, a half-angle tangent per second, so that a slow ball turns harder than a fast one, which is what a curling stone and a biased bowl both do. This is a house law, a shape with fitted constants, and not a model of ice or of a running surface. Whoever describes a surface fits k to a number they can cite and says so. cap is the half-angle tangent turned in one step and vfrac the largest fraction of its speed a ball may lose in one step; smaller values cost segments and buy fidelity to the law.
ATTRIBUTES
L
W
R
The playing area and the ball radius, metres. R is the radius of every body whose kind gives none.
g
Gravity, default 9.81.
vmax
The speed of a full-power strike, metres per second, default 8.
mu
s sliding, r rolling and sp spinning friction, defaults 0.2, 0.02 and 0.044.
e
bb ball-ball restitution, c cushion restitution, cf cushion friction and rc the share of a ball's roll a cushion keeps, defaults 0.95, 0.8, 0.2 and 0.7.
walls
noses
gates
As Physics::Balls::Table returns them.
curve
The curve law's constants: k (default 0, no ball curves whatever its kind), vref 1, vmin 0.1, kmax 1, p an integer 0 to 4 (default 2), cap 0.002 and vfrac 0.1.
kinds
A list of { curve => $strength, follow => $share, r => $radius, m => $mass, mu => $factor, rs => $sweep, vfall => $speed }, every member optional, indexed from 0 by a layout row's fourth element. Default empty, which is a world where every ball is kind 0 at the world's R, mass 1, and none curves. The strength is signed and -1 to 1 by convention: a bowl delivered on the other hand is the same bowl with the sign flipped.
Since 0.04 a kind may also give a body its own size and weight. r is its radius in metres (default the world's R); m its mass, in any unit, since only the ratios between kinds matter (default 1); mu a multiplier on the world's sliding and rolling friction under that body (default 1); rs the radius the body presents to bodies of its own kind (default r), which is how a toppling bowling pin reaches other pins wider than its belly while the ball meets the belly itself; and vfall a peak speed in metres per second above which a body of the kind is down (default 0, never). A down body leaves play when it comes to rest or slows under two centimetres a second, as a potted ball leaves through a gate, and is listed in the outcome's down with where it lay. A world whose kinds give none of these is bit for bit the world it was.
kinds => [
{ r => 0.10795, m => 6.804 }, # 0, a 15 lb bowling ball
{ r => 0.06053, rs => 0.078, m => 1.588, mu => 6, vfall => 0.25 }, # 1, a pin
]
follow, default 1, is how much of its roll a body keeps through a contact with another body. A ball keeps all of it, which is why a rolling cue ball that hits full follows through, and 1 leaves the contact code exactly as it was. A curling stone has no spin to keep and slides off at whatever velocity the contact left it: that is 0, and it is the difference between a takeout that stops on the shot and one that runs on for fifteen metres.
engine
The Physics::Balls::Engine, built lazily.
METHODS
from_table
my $world = Physics::Balls::World->from_table($table, %constants);
kind_count
How many kinds the world declares.
kind_radius
my $r = $world->kind_radius($kind);
The radius of a kind, or the world's R when the kind gives none.
kind_sweep
The radius a kind presents to its own kind, or its radius.
reach
my $rho = $world->reach($kind_a, $kind_b);
The distance at which two bodies of those kinds touch: the sum of the sweep radii between one kind, of the radii between two.
description
The hash the engine is built from.