Changelog
Latest published version: v0.1.0. Full per-release notes are generated frompackages/pixi-wheels/CHANGELOG.md.
pixi-wheels
0.1.0#
First public release. The entries below are the changesets that accumulated on the way to it; nothing before 0.1.0 was published, so a removal listed here undoes something that never shipped.
Minor Changes#
-
a0eecc0Thanks @igaming-bulochka! - Audit fixes across the package.SpinProfile: onlyspinSpeedis required. Every other field falls back to the newDEFAULT_PROFILE(accelerationMs900,minimumSpinTime0,minCruiseMs0,stopDuration4200,minTurns1,maxTurns8,skipDuration450, the two eases).builder.speed()andring.addSpeed()both fill and validate;ring.profileandspeed:changedcarry aResolvedSpinProfile.ring.idle.isActivereports the ring’s idle state instead of alwaysfalse.requestSkip()holds a press made beforeskip.minimumSpinTimeand skips the frame it becomes legal, instead of dropping it.- A skip pressed during the wind-up or the cruise emits
spin:stopping(with the fast-forward’s turns and duration) beforeskip:completed, so slow-down cues fire on every path. WheelBuilder.fromConfig()keeps the id of a first ring that is not calledmaininstead of renaming it.- A weight change after
setResult()that leaves a different section under the fixed landing angle warns at landing (landing-moved). build()rejects adynamic.initialStepoutside the step list, and two wheels built from one builder no longer share a profile table.Pointer.update()drops its unuseddirectionparameter; the crossing direction comes from the rotation delta.DebugRingSkinreuses its labels across layouts instead of re-creating them every frame of a transition.DEFAULT_ANTICIPATION.maxDistanceDeg(150) replaces a hard-coded default.FakeTicker.add()is typed with the exportedTickerCallbackinstead of a private twin of it.
-
76905f7Thanks @igaming-bulochka! - Readable debug overlay. The HUD is a screen-space panel in a corner of the canvas (hud:'top-left'by default, or another corner withscreen: app.screen, or{ x, y }, orfalse) instead of a plate drawn over the wheel. Section ids and angles, the pointer’s local angle and the target sit on upright pills just inside the rim at a constant screen size whatever the wheel’s scale;fontSizesets it. The'inside'/'below'HUD options are gone. -
b473ae9Thanks @igaming-bulochka! - Anticipation reworked so the wheel comes to rest exactly once, on the result.- Every tease rests the pointer just inside the target, next to the divider it shares with the bait (
rest: 0.22 of the arc after crossing the line, 0.15 when it died short of it).rest: 'keep'leaves the landing mode in charge; explicit offsets, angle / position targets andmode: 'exact'are never moved. Addsettle: 'center'to glide to the middle afterwards. - New style
stallreplacesovershoot: the pointer enters the result, crawls toward the bait’s line as if it will cross, and dies just short of it. No stop inside the bait, no roll back.autopicks it when the bait follows the target. stutterno longer halts: the crawl slows tohesitateSpeed(2 deg/s) fordwellMs(600) a hair short of the line, then slips over it inpushMs(700) on a curve that takes over at the crawl speed.- Removed
overshootDegandreturnMs; addedhesitateSpeedandapproachDeg(stall crawl length, default the target’s arc, at most 45). New leg kindhesitate;returnis gone. New exportsDEFAULT_ANTICIPATIONandhermiteStopEase.
- Every tease rests the pointer just inside the target, next to the divider it shares with the bait (
-
68306dcThanks @igaming-bulochka! - Rich labels and fit helpers.- A section can carry
content: any PixiJS container (aText, aSprite, aBitmapText, a Spine instance, a group), or a factory that builds one from aLabelContext. The label layer places, rotates and fits it like a text label and re-fits it whenever the geometry changes.toConfig()keeps the textlabeland dropscontent. - New label orientation
'tangential-in': the top of the label toward the hub, for wheels read from six o’clock. - New
labelFitstyle ('contain','cover','width','height','none') and the helpers behind it:scaleToFit,fitContainer,fitText,labelSlot,chordAt. SpineRingSkingainslabels: trueto draw section labels or content on the disc above the skeleton, and alabelsgetter.SectionLabels.get()now returns the label view (text or content);text()returns theTextof a plain label.- The debug overlay HUD sits inside the ring’s bounding square by default (
hud: 'inside'), so a canvas fitted to the wheel never crops it;hud: 'below'keeps the old placement.
- A section can carry
-
7c45d1fThanks @igaming-bulochka! - The tongue and the pegs are now two solids that may not overlap. The blade is a triangle hinged at the pin -tipWidthacross at its base, tapering to a point at the tip - and the peg is a circle; each frame the contact solves for the smallest swing that keeps the circle outside the triangle. So the tongue yields exactly as far as the peg needs, never cuts through one at any speed or frame rate, and does not fall until the peg has actually gone: on the way down the spring only moves it into clear air. The old model pushed the tip along a curve that had no idea where the peg’s edge was, which showed as the blade clipping straight through pegs.Falling out of that:
pegs.insetnow defaults totipInset + size - 2(the peg ring just inside the first tongue’s tip, a 2 px bite) instead of a flat 9, since pegs out past the tip force the blade to lift clear over them - a much bigger flap.DEFAULT_FLAP.maxAngleis 45, up from 28, so the default geometry has room to clear; amaxAnglebelow what the geometry needs is reported once.elasticitynow means “how far past the minimum”, clamped at 1, because yielding less than the geometry is a blade drawn through a peg.frictionis a fatter peg: a bigger swing, held longer.The contact is solved from where the blade already stands, not from rest: a blade shoved past a peg cannot get home the way it came, and a solver looking for “the smallest swing from zero” hands it an answer on the wrong side. While a peg carries the blade it has no velocity of its own, so the release is one clean swing instead of a flung overshoot chattering against the peg it just cleared.
elasticityandfrictionare both padding on the peg now - a fatter peg swings the blade wider and holds it longer - which keeps them from fighting the contact. A wheel standing still with a peg under the tongue leans the tongue off it instead of leaving it sitting inside.Pegs on the rim work as well as pegs inside the tip, and the two read very differently. A peg sitting deep under the tip cannot slip past sideways, so the blade rides up until its tip lifts clear over it - a 40 to 60 degree swing, the carnival clack - where a shallow bite is a 10 to 20 degree ratchet. The only thing to get right is
maxAngle, and when a cap is below what the geometry needs the warning now names the angle it needs. -
5dbe904Thanks @igaming-bulochka! -flap.drag: the tongue can hold the ring back. While a peg climbs the tip, the disc is drawn up to one contact width of arc behind itself, and springs forward atdragReleaseonce the peg is over the crown, so a wheel crawling to a stop visibly fights every peg. The hold is drawn only:rotationDeg, the crossings and the landing never see it, and it relaxes to zero whenever the ring is not moving, so the wheel still comes to rest exactly on its result. New:FlapConfig.drag(0 by default) andFlapConfig.dragRelease,Ring.visualRotationDeg,Ring.dragDeg,Pointer.dragDeg, and adragfield on the debug snapshot. The debug HUD prints the held arc while it is non-zero. -
0268993Thanks @igaming-bulochka! - The tongue is drawn and pushed like something actually hung on a pin.GraphicsPointerSkinbuilds every shape from one body - a boss around the pin, tapering to the tip, with the tip’s far edge exactlylengthfrom the pin - instead of a free-hand curve that ignored both. NewpinRadiusoption sizes the pin; the boss grows to clear it, and the pin is drawn as a cap with a hole rather than a dot.Pointernow checks that the peg ring runs between the pin and the tip before deflecting: pegs deeper than the tip, or outside the pin, cannot touch the tongue, so it stays still and says so once instead of swinging from nothing. NewPointer.tipRadiusandPointer.reaches(pegs), andcreateTestWheel({ pegs })in the test harness. The debug overlay’s pointer mark is the pointer’s real body too - pin to tip, swung by the deflection, with the rest axis behind it - instead of a short tick at the rim that made the art look like it pivoted somewhere else. -
a6a7d21Thanks @igaming-bulochka! - A physical tongue on pegs.- Every ring has pegs: small circles on the disc, one per divider by default (
.pegs({ size, inset, angles }),.pegs(false)for none), following dynamic sections.ring.pegsexposes them,RingSkinContext.pegshands them to skins,GraphicsRingSkindraws them withpegs: true, and the debug overlay’s newpegslayer draws them with the peg being ridden and each tongue’s contact zone. - The flap is now contact physics: a peg pushes the tongue aside along its rim as it comes through (scaled by
elasticity), carries it on its crown until the peg is through plusfrictionof the contact width, then lets go into the spring (stiffness,damping,maxAngle).tipWidthsets how early a peg starts pushing. At speed a peg that passes within one frame flicks the tongue to the crown.kickandreferenceSpeedare gone. Pointerexposesdeflection,engagedPeg,flap,pinRadiusandcontactHalfWidth(); the HUD prints the first tongue’s deflection. The studio gets Pegs and flap fields;RingConfig.pegsround-trips.
- Every ring has pegs: small circles on the disc, one per divider by default (
Patch Changes#
cf98db8Thanks @igaming-bulochka! - Speed presets ask for stops they can reach.NORMALallows a single turn (its 4.2 s stop needed two turns of 5.3 s before),TURBOasks for 2.0 s,CINEMATICasks for 8 s over one to six turns (it asked for 6.5 s with a three-turn minimum of 12 s). A unit test holds every preset’sstopDurationinside its turn range. Demos on the docs site spin in five to eight seconds instead of nine to seventeen.