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.