Author: Talon
Added: 3y
Updated: Never
mIRC: 7.5+
Hits: 762
Downloads: 27
Review: maroon
Size: 38.07KB
1 0
Login to vote.
mSL Billiards
v1.0
A physics engine attempt in mSL to attempt adequate FPS to play billiards. This is not two player, nor is there any advanced calculations like english, deflection caused by english, spin, spin enduced throw, etc... It's purely elastic collisions with zero spin/roll. There are a TON of hacks to achieve even this level of play-ability without implementing even more complex mathematics into the equation.
Due to the frame-steps being larger than desirable, there are still several issues, attempting to detect and resolve collisions and may result in unusual outcomes, including object balls overlapping, and possibly escaping the playable surface. This situation is amplified with the larger window scaling due to mIRC's outdated graphics handlings with picture windows. Larger surface = slower rendering times of a frame.
With all that said, You can try out mSL-Billiards by loading up this script and typing /B2
You can single click to set the cue ball down if it's grey such as a scratch or table break.
simply move the mouse towards the object ball you wish to shoot at, left click and hold to lock in your aim line, and draw back for power. release the mouse to take the shot.
There are several options in the right-click menu to change various game modes and options like selecting a new table, and which game you wish to play on such table, also scaling to have a larger window rendering of the table.
alias B2 { hfree -w @B2 hadd -m @B2 Table.Break 0 hadd -m @B2 Table.Scratch 1 hadd -m @B2 Table.Scale $iif($1 > 0,$1,9) hadd -m @B2 Table.RailGrid.1.1 22 23 24 1 2 hadd -m @B2 Table.RailGrid.2.1 2 hadd -m @B2 Table.RailGrid.3.1 2 hadd -m @B2 Table.RailGrid.4.1 2 hadd -m @B2 Table.RailGrid.5.1 2 hadd -m @B2 Table.RailGrid.6.1 2 hadd -m @B2 Table.RailGrid.7.1 2 hadd -m @B2 Table.RailGrid.8.1 2 3 4 hadd -m @B2 Table.RailGrid.9.1 4 5 6 hadd -m @B2 Table.RailGrid.10.1 6 hadd -m @B2 Table.RailGrid.11.1 6 hadd -m @B2 Table.RailGrid.12.1 6 hadd -m @B2 Table.RailGrid.13.1 6 hadd -m @B2 Table.RailGrid.14.1 6 hadd -m @B2 Table.RailGrid.15.1 6 hadd -m @B2 Table.RailGrid.16.1 6 7 8 9 10 hadd -m @B2 Table.RailGrid.16.2 10 hadd -m @B2 Table.RailGrid.16.3 10 hadd -m @B2 Table.RailGrid.16.4 10 hadd -m @B2 Table.RailGrid.16.5 10 hadd -m @B2 Table.RailGrid.16.6 10 hadd -m @B2 Table.RailGrid.16.7 10 hadd -m @B2 Table.RailGrid.16.8 10 11 12 13 14 hadd -m @B2 Table.RailGrid.15.8 14 hadd -m @B2 Table.RailGrid.14.8 14 hadd -m @B2 Table.RailGrid.13.8 14 hadd -m @B2 Table.RailGrid.12.8 14 hadd -m @B2 Table.RailGrid.11.8 14 hadd -m @B2 Table.RailGrid.10.8 14 hadd -m @B2 Table.RailGrid.9.8 14 15 16 hadd -m @B2 Table.RailGrid.8.8 16 17 18 hadd -m @B2 Table.RailGrid.7.8 18 hadd -m @B2 Table.RailGrid.6.8 18 hadd -m @B2 Table.RailGrid.5.8 18 hadd -m @B2 Table.RailGrid.4.8 18 hadd -m @B2 Table.RailGrid.3.8 18 hadd -m @B2 Table.RailGrid.2.8 18 hadd -m @B2 Table.RailGrid.1.8 18 19 20 21 22 hadd -m @B2 Table.RailGrid.1.7 22 hadd -m @B2 Table.RailGrid.1.6 22 hadd -m @B2 Table.RailGrid.1.5 22 hadd -m @B2 Table.RailGrid.1.4 22 hadd -m @B2 Table.RailGrid.1.3 22 hadd -m @B2 Table.RailGrid.1.2 22 hadd -m @B2 Table.Highlight 0 hadd -m @B2 Motion 0 B2.GenerateTable $iif($0 >= 2 && $istok(6 7 8 8.5 9,$2,32),$2,6) $iif($3 = 8 || $3 = 9,$3,9) B2.Render 0 B2.GameLoop 0 } alias -l B2.GenerateTable { if ($1 = 6) { var %Width = 72 , %Height = 36 , %Size = $1 } elseif ($1 = 7) { var %Width = 78 , %Height = 39 , %Size = $1 } elseif ($1 = 8) { var %Width = 88 , %Height = 44 , %Size = $1 } elseif ($1 = 8.5) { var %Width = 92 , %Height = 46 , %Size = $1 } else { var %Width = 100 , %Height = 50 , %Size = 9 } var %Game = $2 , %hw = %Width / 2 , %hh = %Height / 2 , %Rail = 2 , %CornerAngle = 54 , %SideAngle = 14 var %CornerThroat = 4.5 , %SideThroat = 5 var %Surface.w = $calc(%Width + %Rail * 2) , %Surface.h = $calc(%Height + %Rail * 2) var %hsw = %surface.w / 2 , %hsh = %surface.h / 2 var %a = $sqrt($calc(%CornerThroat ^ 2 / 2)) var %x = $calc(%hw * -1 + %a) , %y = %hh * -1 tokenize 32 $intersect( %x , %y , $calc(%x + $cos($calc((90 + %CornerAngle) * -1)).deg) , $calc(%y + $sin($calc((90 + %CornerAngle) * -1)).deg) , $calc(%hsw * -1) , $calc(%hsh * -1) ,%hsw,$calc(%hsh * -1),rl) %x %y var %reta = $1 $2 $3 $4 , %retb = $3 $calc($4 * -1) $1 $calc($2 * -1) , %retc = $1 $2 var %x = $calc(0 - %SideThroat / 2) , %y = $calc(%hh * -1) tokenize 32 %x %y $intersect( %x , %y , $calc(%x + $cos($calc((90 - %SideAngle) * -1)).deg) , $calc(%y + $sin($calc((90 - %SideAngle) * -1)).deg) , $calc(%hsw * -1) , $calc(%hsh * -1) ,%hsw,$calc(%hsh * -1),rl) var %reta = %reta $1 $2 $3 $4 , %retb = $3 $calc($4 * -1) $1 $calc($2 * -1) %retb var %x = $calc(%SideThroat / 2) , %y = $calc(%hh * -1) tokenize 32 $intersect( %x , %y , $calc(%x + $cos($calc((90 + %SideAngle) * -1)).deg) , $calc(%y + $sin($calc((90 + %SideAngle) * -1)).deg) , $calc(%hsw * -1) , $calc(%hsh * -1) ,%hsw,$calc(%hsh * -1),rl) %x %y var %reta = %reta $1 $2 $3 $4 , %retb = $3 $calc($4 * -1) $1 $calc($2 * -1) %retb var %a = $sqrt($calc(%CornerThroat ^ 2 / 2)) var %x = $calc(%hw - %a) , %y = %hh * -1 tokenize 32 %x %y $intersect( %x , %y , $calc(%x + $cos($calc((90 - %CornerAngle) * -1)).deg) , $calc(%y + $sin($calc((90 - %CornerAngle) * -1)).deg) , $calc(%hsw * -1) , $calc(%hsh * -1) ,%hsw,$calc(%hsh * -1),rl) var %reta = %reta $1 $2 $3 $4 , %retb = $3 $calc($4 * -1) $1 $calc($2 * -1) %retb var %x = %hw , %y = $calc(%hh - %a) * -1 tokenize 32 $intersect( %x , %y , $calc(%x + $cos($calc(0 - %CornerAngle)).deg) , $calc(%y + $sin($calc(0 - %CornerAngle)).deg) ,%hsw, $calc(%hsh * -1) ,%hsw,%hsh,rl) %x %y var %reta = %reta $1 $2 $3 $4 $3 $calc($4 * -1) $1 $calc($2 * -1) , %retb = %retb , %retc = $calc($1 * -1) $calc($2 * -1) $calc($3 * -1) $calc($4 * -1) $calc($3 * -1) $4 $calc($1 * -1) $2 %retc hadd -m @B2 Table.Size %Size hadd -m @B2 Table.RailCornerAngle %CornerAngle hadd -m @B2 Table.RailSideAngle %SideAngle hadd -m @B2 Table.RailOpening %SideThroat hadd -m @B2 Table.RailCornerOpening %CornerThroat hadd -m @B2 Table.SurfaceSize %Surface.w %Surface.h hadd -m @B2 Table.PlayableSurfaceSize %Width %Height hadd -m @B2 Table.RailSize 2 hadd -m @B2 Table.BorderSize 5 tokenize 32 %reta %retb %retc hadd -m @B2 Table.Surface $1- var %x = 0 | while ($0 >= 4) { inc %x var %Sx = $1 , %Sy = $2 , %Ex = $3 , %Ey = $4 , %LDiffx = $3 - $1 , %LDiffy = $4 - $2 var %LMag = $hypot(%LDiffx,%LDiffy) , %NormalX = $calc((%LDiffy / %LMag) * -1) , %NormalY = %LDiffX / %LMag hadd -m @B2 Table.PlaneSegment. $+ %x $1-4 %NormalX %NormalY %LMag tokenize 32 $3- } var %centerx = $calc(%Width / 4 * -1) var %rs = 1.129 , %ds = %rs * 2 , %xdec = $calc((%ds ^ 2 - %rs ^ 2) ^ .5) if (%Game = 9) { hadd -m @B2 Ball.1 $calc(%centerx) 0 0 0 hadd -m @B2 Ball.2 $calc(%centerx - %xdec) $calc(0 - %rs) 0 0 hadd -m @B2 Ball.3 $calc(%centerx - %xdec) $calc(0 + %rs) 0 0 hadd -m @B2 Ball.4 $calc(%centerx - %xdec * 2) $calc(0 - %rs * 2) 0 0 hadd -m @B2 Ball.9 $calc(%centerx - %xdec * 2) 0 0 0 hadd -m @B2 Ball.5 $calc(%centerx - %xdec * 2) $calc(%rs * 2) 0 0 hadd -m @B2 Ball.6 $calc(%centerx - %xdec * 3) $calc(0 - %rs * 1) 0 0 hadd -m @B2 Ball.7 $calc(%centerx - %xdec * 3) $calc(%rs * 1) 0 0 hadd -m @B2 Ball.8 $calc(%centerx - %xdec * 4) 0 0 0 hadd -m @B2 Table.Balls 33279 hadd -m @B2 Table.Game 9 } else { hadd -m @B2 Ball.1 $calc(%centerx) 0 0 0 hadd -m @B2 Ball.9 $calc(%centerx - %xdec) $calc(0 - %rs) 0 0 hadd -m @B2 Ball.14 $calc(%centerx - %xdec) $calc(0 + %rs) 0 0 hadd -m @B2 Ball.2 $calc(%centerx - %xdec * 2) $calc(0 - %rs * 2) 0 0 hadd -m @B2 Ball.8 $calc(%centerx - %xdec * 2) 0 0 0 hadd -m @B2 Ball.6 $calc(%centerx - %xdec * 2) $calc(%rs * 2) 0 0 hadd -m @B2 Ball.10 $calc(%centerx - %xdec * 3) $calc(0 - %rs * 3) 0 0 hadd -m @B2 Ball.7 $calc(%centerx - %xdec * 3) $calc(0 - %rs * 1) 0 0 hadd -m @B2 Ball.15 $calc(%centerx - %xdec * 3) $calc(%rs * 1) 0 0 hadd -m @B2 Ball.13 $calc(%centerx - %xdec * 3) $calc(%rs * 3) 0 0 hadd -m @B2 Ball.3 $calc(%centerx - %xdec * 4) $calc(0 - %rs * 4) 0 0 hadd -m @B2 Ball.11 $calc(%centerx - %xdec * 4) $calc(0 - %rs * 2) 0 0 hadd -m @B2 Ball.4 $calc(%centerx - %xdec * 4) 0 0 0 hadd -m @B2 Ball.12 $calc(%centerx - %xdec * 4) $calc(%rs * 2) 0 0 hadd -m @B2 Ball.5 $calc(%centerx - %xdec * 4) $calc(%rs * 4) 0 0 hadd -m @B2 Table.Balls $base($str(1,16),2,10) hadd -m @B2 Table.Game 8 } hadd -m @B2 Ball.16 $calc(%centerx * -1 + 1.125) 0 $iif($r(1,360),$calc($cos($v1).deg * 0.00) $calc($sin($v1).deg * 0.00),0 0) } alias -l B2.Quadratic { if ($1 != 0 && $calc($2 ^ 2 - 4 * $1 * $3) > 0) { return $calc((0 - $2 - $sqrt($v1)) / (2 * $1)) } } alias -l B2.GridCoord { return $calc($hget(@B2,$+(Grid.,$1,.,$2)) + 0) } alias -l B2.Grid9x9 { return $or($or($or($or($or($or($or($or($B2.GridCoord($calc($1 - 1),$calc($2 - 1)),$B2.GridCoord($1,$calc($2 - 1))),$B2.GridCoord($calc($1 + 1),$calc($2 - 1))),$B2.GridCoord($calc($1 - 1),$2)),$B2.GridCoord($1,$2)),$B2.GridCoord($calc($1 + 1),$2)),$B2.GridCoord($calc($1 - 1),$calc($2 + 1))),$B2.GridCoord($1,$calc($2 + 1))),$B2.GridCoord($calc($1 + 1),$calc($2 + 1))) } alias -l B2.SetBall { hadd -m @B2 $1- } alias -l B2.GameLoop { if ($window(@B2)) { ;=== Find the Delta Time (the time passed since our last loop run) if ($1) { var %t = $ticks , %dt = %t - $1 , %Motion = $Hget(@B2,Motion) , %Break = $hget(@B2,Table.Break) , %Balls = $hget(@B2,Table.Balls) } else { var %t = $ticks , %dt = 0 , %Motion = 0 } if (%Motion) { hdel -w @B2 Grid.* hdel -w @B2 Closest.* noop $hfind(@B2,Ball.*,0,w,B2.UpdateBall $1 %dt) noop $hfind(@B2,Ball.*,0,w,B2.FixBallCollisions $1 %dt) noop $hfind(@B2,Ball.*,0,w,B2.FixPocketCollisions $1 %dt) var %Motion = $hget(@B2,Motion) if (!%motion) { hadd -m @B2 Table.Break 1 } } var %Highlight = $hget(@B2,Table.Highlight) + 0.05 if (%Highlight > 6) { var %Highlight = 1 } hadd -m @B2 Table.Highlight %Highlight if (!%motion && %balls = 32768) { B2 $hget(@B2,Table.Scale) $hget(@B2,Table.Size) $hget(@B2,Table.Game) } ;=== Render the game scene. if ($calc($ticks - $2) > 15) { B2.Render $v1 tokenize 32 $1 } .timer $+ @B2 -oh 1 0 B2.GameLoop %t $iif($2,$2,$1) } } alias -l B2.UpdateBall { var %ball = $1 , %dt = $2 , %Bnum = $gettok(%Ball,2,46) tokenize 32 $hget(@B2,%Ball) $hget(@B2,Table.SurfaceSize) $hget(@B2,Motion) if ($0 = 7) { var %x = $1 , %y = $2 , %vx = $3 , %vy = $4 , %Gw = $calc($5 / 16) , %Gh = $calc($6 / 8) , %BGw = $calc($5 / 32) , %BGh = $calc($6 / 16) , %Motion = $calc($7 + 0) var %BGx = $calc(%x // %BGw) + 17 , %BGy = $calc(%y // %BGh) + 9 , %val = $B2.GridCoord(%BGx,%BGy) hadd -m @B2 $+(Grid.,%BGx,.,%BGy)) $biton(%val,%Bnum) if ($calc(%vx ^ 2 + %vy ^ 2) != 0) { var %m = $v1 , %ff = -0.0003 , %fx = %vx * %ff , %fy = %vy * %ff var %afx = %fx * %dt , %afy = %fy * %dt var %vx = %vx + %afx , %vy = %vy + %afy if (%m < 0.000007) { var %vx = 0 , %vy = 0 , %Motion = $bitoff(%Motion,%Bnum) } else { var %Motion = $biton(%Motion,%Bnum) } var %x = $calc(%x + %vx * %dt) , %y = $calc(%y + %vy * %dt) hadd -m @B2 %Ball %x %y %vx %vy var %Gx = $calc(%x // %Gw) + 9 , %Gy = $calc(%y // %Gh) + 5 , %val = $B2.GridCoord(%Gx,%Gy) if (%Gx = 1 || %Gx isnum 8-9 || %Gx = 16) && (%Gy = 1 || %Gy = 8) { B2.FixRailCollisions %Ball %dt %Gx %Gy 1 } elseif ((%Gx isnum 1-16) && (%Gy = 1 || %Gy = 8)) || ((%Gy isnum 1-8) && (%Gx = 1 || %Gx = 16)) { B2.FixRailCollisions %Ball %dt %Gx %Gy } } else { var %Motion = $bitoff(%Motion,%Bnum) } hadd -m @B2 Motion %Motion } } alias -l B2.FixRailCollisions { var %ball = $1 , %dt = $2 , %Gx = $3 , %Gy = $4 , %Multiple = $5 , %Bnum = $gettok(%Ball,2,46) tokenize 32 $hget(@B2,%Ball) if ($0 = 4) { var %x = $1 , %y = $2 , %vx = $3 , %vy = $4 var %Planes = $hget(@B2,$+(Table.RailGrid.,%Gx,.,%Gy)) var %a = $numtok(%Planes,32) while (%a) { tokenize 32 $hget(@B2,$+(Table.PlaneSegment.,$gettok(%Planes,%a,32))) var %Sx = $1 , %Sy = $2 , %Ex = $3 , %Ey = $4 , %LDiffx = $3 - $1 , %LDiffy = $4 - $2 var %LMag = $7 , %NormalX = $5 , %NormalY = $6 var %dv = $calc(%vx * %NormalX + %vy * %NormalY) if (%dv < 0) { var %d1 = $calc(%LDiffX ^ 2 + %LDiffY ^ 2) var %t = $calc(((%x - %Sx) * %LDiffx + (%y - %Sy) * %LDiffy) / %d1) var %nx = $calc(%Sx + %t * %LDiffx) , %ny = $calc(%Sy + %t * %LDiffy) var %dist = $hypot($calc(%nx - %x),$calc(%ny - %y)) if (%t >= 0 && %t <= 1 && %dist < 1.125) { var %scalar = $calc(-2 * (%NormalX * %vx + %vy * %NormalY)) var %dt = $B2.Quadratic($calc(%d2 * %d2),$calc(2 * %d1 * %d2),$calc(%d1 * %d1 - 1.123^2)) if (%dt < 0) { var %x = $calc(%x + %vx * %dt) , %y = $calc(%y + %vy * %dt) var %vx = $calc(%vx + %NormalX * %scalar) , %vy = $calc(%vy + %NormalY * %scalar) var %x = $calc(%x + %vx * (%dt * -1)) , %y = $calc(%y + %vy * (%dt * -1)) hadd -m @B2 %Ball %x %y %vx %vy } else { hadd -m @B2 %Ball %x %y $calc(%vx + %NormalX * %scalar) $calc(%vy + %NormalY * %scalar) } break } else { var %diffx = %Ex - %x , %diffy = %Ey - %y , %vdiffx = 0 - %vx , %vdiffy = 0 - %vy , %mag = $hypot(%diffx,%diffy) , %NormalX = %diffx / %mag , %NormalY = %diffy / %mag if (%mag < 1.265625) { var %scalar = $calc(-2 * (%NormalX * %vx + %vy * %NormalY)) var %dt = $B2.Quadratic($calc(%vdiffx ^ 2 + %vdiffy ^ 2),$calc(2 * $calc(%diffx * %vdiffx + %diffy * %vdiffy)),$calc((%diffx ^ 2 + %diffy ^ 2) - 1.123^2)) if (%dt < 0) { var %x = $calc(%x + %vx * %dt) , %y = $calc(%y + %vy * %dt) var %diffx = %Ex - %x , %diffy = %Ey - %y , %vdiffx = 0 - %vx , %vdiffy = 0 - %vy , %mag = $hypot(%diffx,%diffy) , %NormalX = %diffx / %mag , %NormalY = %diffy / %mag var %scalar = $calc(-2 * (%NormalX * %vx + %vy * %NormalY)) var %vx = $calc(%vx + %NormalX * %scalar) , %vy = $calc(%vy + %NormalY * %scalar) var %x = $calc(%x + %vx * (%dt * -1)) , %y = $calc(%y + %vy * (%dt * -1)) hadd -m @B2 %Ball %x %y %vx %vy } else { hadd -m @B2 %Ball %x %y $calc(%vx + %NormalX * %scalar) $calc(%vy + %NormalY * %scalar) } break } } } dec %a } } } alias -l B2.FixPocketCollisions { var %ball = $1 , %dt = $2 , %Bnum = $gettok(%Ball,2,46) , %Balls = $hget(@B2,Table.Balls) tokenize 32 $hget(@B2,%Ball) $hget(@B2,Table.SurfaceSize) $hget(@B2,Motion) if ($0 = 7) { var %x = $1 , %y = $2 , %vx = $3 , %vy = $4 , %Sw = $5 , %Sh = $6 , %Gw = $calc($5 / 16) , %Gh = $calc($6 / 8) , %Motion = $calc($7 + 0) var %Gx = $calc(%x // %Gw) + 9 , %Gy = $calc(%y // %Gh) + 5 var %BGx = $calc(%x // %BGw) + 17 , %BGy = $calc(%y // %BGh) + 9 , %val = $B2.GridCoord(%BGx,%BGy) if (%Gx = 1) { var %px = %Sw / -2 } elseif (%Gx = 16) { var %px = %Sw / 2 } else { var %px = 0 } if (%Gy = 1) { var %py = $calc(%Sh / -2 - $iif(!%px,2.25,0)) } elseif (%Gy = 8) { var %py = $calc(%Sh / 2 + $iif(!%px,2.25,0)) } if (%Gx = 1 || %Gx isnum 8-9 || %Gx = 16) && (%Gy = 1 || %Gy = 8) { if ($calc((%px - %x) ^ 2 + (%py - %y) ^ 2) <= 16) { var %val = $bitoff(%val,%Bnum) , %Motion = $bitoff(%Motion,%Bnum) hadd -m @B2 $+(Grid.,%BGx,.,%BGy) %val hadd -m @B2 Motion %Motion hdel -w @B2 %Ball if (%BNum != 16) { hadd -m @B2 Table.Balls $bitoff(%Balls,%Bnum) } else { hadd -m @B2 Table.Scratch 1 } } } } } alias -l B2.FixBallCollisions { var %ball = $1 , %dt = $2 , %Bnum = $gettok(%Ball,2,46) , %Break = $hget(@B2,Table.Break) , %Scratch = $hget(@B2,Table.Scratch) tokenize 32 $hget(@B2,Table.SurfaceSize) var %Gw = $calc($1 / 32) , %Gh = $calc($2 / 16) tokenize 32 $hget(@B2,%Ball) if ($0 = 4) { var %x = $1 , %y = $2 , %vx = $3 , %vy = $4 , %Gx = $calc(%x // %gw) + 17 , %Gy = $calc(%y // %gh) + 9 if ($calc(%vx ^ 2 + %vy ^ 2) != 0) { var %val = $bitoff($B2.Grid9x9(%Gx,%Gy),%BNum) if (%Scratch) { var %val = $bitoff(%val,16) } var %bin = $base(%val,10,2) , %len = $len(%bin) , %match = 1 while ($pos(%bin,1,%match)) { var %c = $calc(%len - $v1 +1) , %CBall = Ball. $+ %c tokenize 32 $hget(@B2,%CBall) var %cx = $1 , %cy = $2 , %cvx = $3 , %cvy = $4 var %diffx = %cx - %x , %diffy = %cy - %y , %mag = $calc(%diffx ^ 2 + %diffy ^ 2) if (%mag < 5.0625) { var %t = $B2.BallCollisionTime(%bnum,%c) var %x = $calc(%x + %vx * %t) , %y = $calc(%y + %vy * %t) var %cx = $calc(%cx + %cvx * %t) , %cy = $calc(%cy + %cvy * %t) var %diffx = %cx - %x , %diffy = %cy - %y , %magsq = $calc(%diffx ^ 2 + %diffy ^ 2) var %mag = $hypot(%diffx,%diffy) , %NormX = %diffx / %mag , %NormY = %diffy / %mag , %VelAlongNormal = $calc((%cvx - %vx) * %NormX + (%cvy - %vy) * %NormY) if (%VelAlongNormal <= 0) { var %scalar = $calc((%vx * %NormX + %vy * %NormY) - (%cvx * %NormX + %cvy * %NormY)) var %vx = %vx - $calc(%NormX * %scalar) , %vy = %vy - $calc(%NormY * %scalar) var %cvx = %cvx + $calc(%NormX * %scalar) , %cvy = %cvy + $calc(%NormY * %scalar) var %x = $calc(%x + %vx * (%t * -1)) , %y = $calc(%y + %vy * (%t * -1)) var %cx = $calc(%cx + %cvx * (%t * -1)) , %cy = $calc(%cy + %cvy * (%t * -1)) var %Gx = $calc(%x // %gw) + 17 , %Gy = $calc(%y // %gh) + 9 B2.SetBall %Ball %x %y %vx %vy B2.SetBall %CBall %cx %cy %cvx %cvy } } inc %match } } } } alias -l B2.DrawPoly { drawline -n @B2.Surface $iif($5 isnum,$5,3) 1 $regsubex($hget(@B2,$1),/([^ ]+) ([^ ]+)/g,$calc(\1 * [ $4 ] + [ $2 ] ) $calc(\2 * [ $4 ] + [ $3 ] )) } alias -l B2.DrawBall { var %scale = $4 , %BNum = $gettok($1,2,46) , %hw = $2 , %hh = $3 , %chart = 8 12 4 6 7 31 5 1 84 , %Game = $hget(@B2,Table.Game) tokenize 32 $hget(@B2,$1) var %x = $1 , %y = $2 , %vx = $3 , %vy = $4 , %size = $ceil($calc(1.125 * %scale)) , %color = $gettok(%chart,%bnum,32) if (%BNum = 16) { var %scratch = $hget(@B2,Table.Scratch) } drawdot -n @B2 14 %size $calc(%x * %scale + %hw) $calc(%y * %scale + %hh) drawdot -n @B2 1 $calc(%size - 1) $calc(%x * %scale + %hw) $calc(%y * %scale + %hh) if (%Game = 8) { if (%BNum <= 7) { var %color = 4 } else { var %color = 8 } if (%BNum = 8) { var %color = 1 } } if (%BNum = 16) { if (!%scratch) { var %color = 0 } else { var %color = 94 } } drawdot -n @B2 $iif(%color,$v1,0) $calc(%size - 2) $calc(%x * %scale + %hw) $calc(%y * %scale + %hh) } alias -l B2.Render { var %s = $hget(@B2,Table.Scale) , %Motion = $hget(@B2,Motion) tokenize 32 $hget(@B2,Table.SurfaceSize) $hget(@B2,Table.PlayableSurfaceSize) $1- var %w = $1 * %s , %h = $2 * %s , %iw = $3 , %ih = $4 tokenize 32 $5- var %hw = %w / 2 , %hh = %h / 2 , %1 = $1- if (!$window(@B2)) || ($window(@B2).dw != %w && $window(@B2).dh != %h) { window -dBpf +nt @B2 -1 -1 %w %h window -c @B2.Surface window -hpf @B2.Surface -1 -1 %w %h window -hpf @B2.Surface -1 -1 %w %h ;== Clear the window drawrect -nf @B2.Surface 35 0 0 0 $calc(%w * %s) $calc(%h * %s) ;== Draw the pockets drawdot -n @B2.Surface 13 $calc(4 * %s) 0 0 drawdot -n @B2.Surface 13 $calc(4 * %s) %hw $calc(0 - 2.25 * %s) drawdot -n @B2.Surface 13 $calc(4 * %s) 0 %h drawdot -n @B2.Surface 13 $calc(4 * %s) %w 0 drawdot -n @B2.Surface 13 $calc(4 * %s) %hw $calc(%h + 2.25 * %s) drawdot -n @B2.Surface 13 $calc(4 * %s) %w %h ;== Draw the Head Spot var %cx = $calc(%iw / 4 * -1) , %cy = 0 drawdot -n @B2.Surface 47 $calc(0.7 * %s) $calc(%cx * %s + %hw) $calc(%cy * %s + %hh) drawdot -n @B2.Surface 35 $calc(0.6 * %s) $calc(%cx * %s + %hw) $calc(%cy * %s + %hh) drawdot -n @B2.Surface 47 $calc(0.25 * %s) $calc(%cx * %s + %hw) $calc(%cy * %s + %hh) drawline -n @B2.Surface 47 1 $calc(%cx * -1 * %s + %hw) 0 $calc(%cx * -1 * %s + %hw) %h ;== Draw Playable Surface B2.DrawPoly Table.Surface %hw %hh %s 1 ;== Fill the rails drawfill -n @B2.Surface 47 1 $calc(-2.5 * %s + %hw) 1 drawfill -n @B2.Surface 47 1 $calc(-2.5 * %s + %hw) $calc(%h - 1) drawfill -n @B2.Surface 47 1 $calc(2.5 * %s + %hw) 1 drawfill -n @B2.Surface 47 1 $calc(2.5 * %s + %hw) $calc(%h - 1) drawfill -n @B2.Surface 47 1 1 %hh drawfill -n @B2.Surface 47 1 $calc(%w - 1) %hh drawpic -ns @B2.Surface $calc(-4 * %s + %hw) $calc(-4 * %s + %hh) $calc(8 * %s) $calc(8 * %s) 0 0 32 32 $qt($mircexe) } drawrect -nf @B2 1 0 0 0 $calc(128 * %s) $calc(78 * %s) ;== DrawCopy the Table drawcopy -nt @B2.Surface $color(13) 0 0 %w %h @B2 0 0 %w %h var %WaterMark = $hget(@B2,Table.Game) $+ -Ball Pool by: Talon , %FSize = $calc($window(@B2).fontsize + %s) var %Ww = $width(%WaterMark,$window(@B2).font,%FSize) , %Wh = $height(%WaterMark,$window(@B2).font,%FSize) drawtext -n @B2 47 $qt($window(@B2).font) %FSize $calc(0 - %Ww + %w - %FSize) $calc(0 - %Wh + %h - %FSize) %WaterMark ;== Draw the Highlight if ($hget(@B2,Table.Game) = 9) { var %bin = $base($hget(@B2,Table.Balls),10,2,16) , %highlight = $hget(@B2,Table.Highlight) * %s var %bnum = $calc(16 - $Pos(%bin,1,$pos(%bin,1,0)) + 1) , %chart = 8 12 4 6 7 31 5 1 84 tokenize 32 $hget(@B2,Ball. $+ %bnum) var %x = $1 , %y = $2 , %vx = $3 , %vy = $4 if (!%Motion && $0 = 4 && %Bnum != 16) { drawrect -ne @B2 $gettok(%chart,%bnum,32) 3 $calc(%x * %s + %hw - %highlight / 2) $calc(%y * %s + %hh - %highlight / 2) %highlight %highlight } } ;== Draw the balls noop $hfind(@B2,Ball.*,0,w,B2.DrawBall $1 %hw %hh %s) ;=========================================== ; FPS Related @Window Drawing routines here ;=========================================== if (!%Motion) { tokenize 32 $hget(@B2,Ball.16) var %x = $1 , %y = $2 , %vx = $3 , %vy = $4 var %break = $hget(@B2,Table.Break) , %scratch = $hget(@B2,Table.Scratch) if (!%break) { drawtext -n @B2 0 $calc(0 + %hw) $calc(%hh + 12) How To Play: drawtext -n @B2 0 $calc(0 + %hw) $calc(%hh + 24) Move mouse to aim. drawtext -n @B2 0 $calc(0 + %hw) $calc(%hh + 36) Hold Mouse1 and draw drawtext -n @B2 0 $calc(0 + %hw) $calc(%hh + 48) back for power. } var %1- = $1- if (!%scratch) { tokenize 32 $hget(@B2,Closest.Ball) if ($0 = 2) { var %closest = $2 , %t = $1 tokenize 32 $click(@B2,$click(@B2,0)) ;if ($0 = $2) { var %mx = $calc($1 - %hw) / %s , %my = $calc($2 - %hh) / %s } ;else { } var %mx = $calc(%x + %vx * %t) , %my = $calc(%y + %vy * %t) var %dx = %mx - %x , %dy = %my - %y , %mag = $hypot(%dx,%dy) var %dx = %dx / %mag , %dy = %dy / %mag var %nx = %x + $calc(%dx * %t) , %ny = %y + $calc(%dy * %t) , %size = $ceil($calc(1.125 * %s)) tokenize 32 $hget(@B2,Ball. $+ %closest) var %cx = $1 , %cy = $2 , %cvx = $3 , %cvy = $4 var %diffx = %nx - %cx , %diffy = %ny - %cy , %mag = $hypot(%diffx,%diffy) , %NormX = %diffx / %mag , %Normy = %diffy / %mag var %scalar = $calc((%dx * %NormX + %dy * %NormY) - (%cvx * %NormX + %cvy * %NormY)) var %ox = %x , %oy = %y , %ovx = %vx , %ovy = %vy var %vx = %dx - $calc(%NormX * %scalar) , %vy = %dy - $calc(%NormY * %scalar) var %cvx = %cvx + $calc(%NormX * %scalar) , %cvy = %cvy + $calc(%NormY * %scalar) var %Mv = $hypot(%vx,%vy) , %Mcv = $hypot(%cvx,%cvy) var %cvx = %cvx / %mcv , %cvy = %cvy / %Mcv var %mvx = %vx / %mv , %mvy = %vy / %mv drawdot -n @B2 14 %size $calc(%nx * %s + %hw) $calc(%ny * %s + %hh) drawdot -n @B2 0 $calc(%size - 1) $calc(%nx * %s + %hw) $calc(%ny * %s + %hh) drawdot -n @B2 94 $calc(%size - 2) $calc(%nx * %s + %hw) $calc(%ny * %s + %hh) drawline -n @B2 9 2 $calc(%cx * %s + %hw) $calc(%cy * %s + %hh) $calc((%nx + %cvx * 10.25) * %s + %hw) $calc((%ny + %cvy * 10.25) * %s + %hh) ;=== Draw our plane segment's Normal arrow heads var %hs = 10 , %ra = $atan2($calc(%Ny - %cy),$calc(%Nx - %cx)) , %na = %ra - 0.523599 , %pa = %ra + 0.523599 , %nc = %hs * $cos(%na) , %ns = %hs * $sin(%na) , %pc = %hs * $cos(%pa) , %ps = %hs * $sin(%pa) drawline -n @B2 9 2 $calc((%nx + %cvx * 10.25) * %s + %hw) $calc((%ny + %cvy * 10.25) * %s + %hh) $calc((%nx + %cvx * 10.25) * %s + %Nc + %hw) $calc((%ny + %cvy * 10.25) * %s + %Ns + %hh) drawline -n @B2 9 2 $calc((%nx + %cvx * 10.25) * %s + %hw) $calc((%ny + %cvy * 10.25) * %s + %hh) $calc((%nx + %cvx * 10.25) * %s + %Pc + %hw) $calc((%ny + %cvy * 10.25) * %s + %Ps + %hh) drawline -n @B2 0 2 $calc(%nx * %s + %hw) $calc(%ny * %s + %hh) $calc((%nx + %mvx * 8) * %s + %hw) $calc((%ny + %mvy * 8) * %s + %hh) ;=== Draw our plane segment's Normal arrow heads var %hs = 10 , %ra = $atan2($calc(%ny - (%ny + %mvy * 8)),$calc(%nx - (%nx + %mvx * 8))) , %na = %ra - 0.523599 , %pa = %ra + 0.523599 , %nc = %hs * $cos(%na) , %ns = %hs * $sin(%na) , %pc = %hs * $cos(%pa) , %ps = %hs * $sin(%pa) drawline -n @B2 0 2 $calc((%nx + %mvx * 8) * %s + %hw) $calc((%ny + %mvy * 8) * %s + %hh) $calc((%nx + %mvx * 8) * %s + %NC + %hw) $calc((%ny + %mvy * 8) * %s + %NS + %hh) drawline -n @B2 0 2 $calc((%nx + %mvx * 8) * %s + %hw) $calc((%ny + %mvy * 8) * %s + %hh) $calc((%nx + %mvx * 8) * %s + %PC + %hw) $calc((%ny + %mvy * 8) * %s + %PS + %hh) drawline -n @B2 0 2 $calc(%x * %s + %hw) $calc(%y * %s + %hh) $calc(%nx * %s + %hw) $calc(%ny * %s + %hh) tokenize 32 $click(@B2,$click(@B2,0)) $mouse.x $Mouse.y var %Click.x1 = $1 , %Click.y1 = $2 , %Click.x2 = $3 , %Click.y2 = $4 var %cldx = $3 - $1 , %cldy = $4 - $2 , %mag = $hypot(%cldx,%cldy) if ($0 = 4) { drawtext -n @B2 14 $calc((%x - 2) * %s + %hw) $calc((%y + 1) * %s + %hh) $iif(%mag > 100,100,$round(%mag,2)) var %pmag = $iif(%mag > 100,100,$v1) , %powershift = $calc(-2.25 * %pmag / 100) } else { var %pmag = 0 , %powershift = 0 } drawline -n @B2 41 5 $calc((%ox + %ovx * (-1.125 + %powershift)) * %s + %hw) $calc((%oy + %ovy * (-1.125 + %powershift)) * %s + %hh) $calc((%ox + %ovx * (-36 + %powershift)) * %s + %hw) $calc((%oy + %ovy * (-36 + %powershift)) * %s + %hh) } else { tokenize 32 $click(@B2,$click(@B2,0)) $mouse.x $Mouse.y var %Click.x1 = $1 , %Click.y1 = $2 , %Click.x2 = $3 , %Click.y2 = $4 var %cldx = $3 - $1 , %cldy = $4 - $2 , %mag = $iif($hypot(%cldx,%cldy) > 100,100,$v1) if ($0 = 4) { drawtext -n @B2 14 $calc((%x - 2) * %s + %hw) $calc((%y + 1) * %s + %hh) $round(%mag,2) } else { var %mag = 0 } tokenize 32 $hget(@B2,Closest.Rail) if ($0 >= 3) { var %t = $1 , %rail = $2 , %Endpoint = $3 var %nx = $calc(%x + %vx * $1) , %ny = $calc(%y + %vy * $1) , %size = $ceil($calc(1.125 * %s)) tokenize 32 $hget(@B2,$+(Table.PlaneSegment.,%Rail)) var %Sx = $1 , %Sy = $2 , %Ex = $3 , %Ey = $4 , %LDiffX = $3 - $1 , %LDiffy = $4 - $2 , %NormalX = $5 , %NormalY = $6 , %LMag = $7 if (%endpoint = -1) { var %diffx = %Ex - %nx , %diffy = %Ey - %ny , %mag = $hypot(%diffx,%diffy) , %NormalX = %diffx / %mag , %NormalY = %diffy / %mag } var %scalar = $calc(-1.8 * (%NormalX * %vx + %vy * %NormalY)) var %powershift = $calc(-2.25 * %mag / 100) drawline -n @B2 41 5 $calc((%x + %vx * (-1.125 + %powershift)) * %s + %hw) $calc((%y + %vy * (-1.125 + %powershift)) * %s + %hh) $calc((%x + %vx * (-36 + %powershift)) * %s + %hw) $calc((%y + %vy * (-36 + %powershift)) * %s + %hh) var %vx = $calc(%vx + %NormalX * %scalar) , %vy = $calc(%vy + %NormalY * %scalar) , %mag = $hypot(%vx,%vy) var %gx = $calc(%nx + %vx / %mag * 8) , %gy = $calc(%ny + %vy / %mag * 8) drawdot -n @B2 14 %size $calc(%nx * %s + %hw) $calc(%ny * %s + %hh) drawdot -n @B2 0 $calc(%size - 1) $calc(%nx * %s + %hw) $calc(%ny * %s + %hh) drawdot -n @B2 94 $calc(%size - 2) $calc(%nx * %s + %hw) $calc(%ny * %s + %hh) drawline -n @B2 0 2 $calc(%nx * %s + %hw) $calc(%ny * %s + %hh) $calc(%x * %s + %hw) $calc(%y * %s + %hh) drawline -n @B2 0 2 $calc(%nx * %s + %hw) $calc(%ny * %s + %hh) $calc(%gx * %s + %hw) $calc(%gy * %s + %hh) ;=== Draw our plane segment's Normal arrow heads var %hs = 10 , %ra = $atan2($calc(%gy - %ny),$calc(%gx - %nx)) , %na = %ra - 0.523599 , %pa = %ra + 0.523599 , %nc = %hs * $cos(%na) , %ns = %hs * $sin(%na) , %pc = %hs * $cos(%pa) , %ps = %hs * $sin(%pa) drawline -n @B2 0 2 $calc(%gx * %s + %hw) $calc(%gy * %s + %hh) $calc(%gx * %s - %NC + %hw) $calc(%gy * %s - %NS + %hh) drawline -n @B2 0 2 $calc(%gx * %s + %hw) $calc(%gy * %s + %hh) $calc(%gx * %s - %PC + %hw) $calc(%gy * %s - %PS + %hh) ;drawline -n @B2 0 2 $calc(%nx * %s + %hw) $calc(%ny * %s + %hh) $calc(%nx * %s + %nc + %hw) $calc(%ny * %s + %pc + %hh) } ;drawline -n @B2 0 2 $mouse.x $mouse.y $calc(%x * %s + %hw) $calc(%y * %s + %hh) } } } tokenize 32 %1 drawdot @B2 titlebar @B2 Updated: $1 ms $round($calc(1000 / $1),2) FPS } alias -l B2.PlaneSegmentCollisionTime { var %Ball = $1 , %Rail = $2 tokenize 32 $hget(@B2,$+(Ball.,$1)) $hget(@B2,$+(Table.PlaneSegment.,$2)) var %x = $1 , %y = $2 , %vx = $3 , %vy = $4 , %Sx = $5 , %Sy = $6 , %Ex = $7 , %Ey = $8 , %LDiffX = $1 - $5 , %LDiffy = $2 - $6 , %NormalX = $9 , %NormalY = $10 , %LMag = $11 ;=== Solve for time to plane var %d1 = $calc(%LDiffX * %NormalX + %LDiffy * %NormalY) , %d2 = $calc(%vx * %NormalX + %vy * %NormalY) var %dt = $B2.Quadratic($calc(%d2 * %d2),$calc(2 * %d1 * %d2),$calc(%d1 * %d1 - 1.123^2)) if (%dt >= 0) { var %cx = $calc(%x + %vx * %dt) , %cy = $calc(%y + %vy * %dt) ;=== Solve if when on plane if we're within bounds of segment. var %LDiffx = %Ex - %Sx , %LDiffy = %Ey - %Sy var %d1 = $calc(%LDiffX ^ 2 + %LDiffY ^ 2) var %t = $calc(((%cx - %Sx) * %LDiffx + (%cy - %Sy) * %LDiffy) / %d1)) if (%t >= 0 && %t <= 1) { var %nx = $calc(%Sx + %t * %LDiffx) , %ny = $calc(%Sy + %t * %LDiffy) return %dt %t } else { var %diffx = %Ex - %x , %diffy = %Ey - %y , %vdiffx = 0 - %vx , %vdiffy = 0 - %vy var %EndPoint = $B2.Quadratic($calc(%vdiffx ^ 2 + %vdiffy ^ 2),$calc(2 * $calc(%diffx * %vdiffx + %diffy * %vdiffy)),$calc((%diffx ^ 2 + %diffy ^ 2) - 1.123^2)) var %cx = $calc(%x + %vx * %EndPoint) , %cy = $calc(%y + %vy * %EndPoint) if ($calc((%cx - %Ex)^2 + (%cy - %Ey)^2) <= 1.265625) { return %EndPoint -1 } } } } alias -l B2.ClosestRailCollision { var %Ball = $1 , %Rails = 24 , %Time , %Rail , %EndPoint while (%Rails) { tokenize 32 $B2.PlaneSegmentCollisionTime(%Ball,%Rails) var %t = $1 , %Et = $2 if (%t) { if (!%Time && %t >= 0) || (%t >= 0 && %t < %Time) { var %Time = %t , %Rail = %Rails , %EndPoint = %Et } } dec %Rails } if (%Time != $null) { return %Time %Rail %EndPoint } } alias -l B2.BallCollisionTime { var %BallA = $1 , %BallB = $2 tokenize 32 $hget(@B2,$+(Ball.,$1)) $hget(@B2,$+(Ball.,$2)) var %x = $1 , %y = $2 , %vx = $3 , %vy = $4 , %cx = $5 , %cy = $6 , %cvx = $7 , %cvy = $8 var %diffx = %cx - %x , %diffy = %cy - %y , %vdiffx = %cvx - %vx , %vdiffy = %cvy - %vy if ($0 = 8) { var %a = $calc(%vdiffx ^ 2 + %vdiffy ^ 2) var %b = 2 * $calc(%diffx * %vdiffx + %diffy * %vdiffy) var %c = $calc(%diffx ^ 2 + %diffy ^ 2) - 5.0625 return $B2.Quadratic(%a,%b,%c) } } alias -l B2.ClosestBallCollision { var %Ball = $1 , %Balls = 16 , %RTime , %RBall while (%Balls) { if (%Balls != %Ball) { var %Time = $B2.BallCollisionTime(%Ball,%Balls) } if (!%RTime && %Time >= 0) || (%Time >= 0 && %Time < %RTime) { var %RTime = %Time , %RBall = %balls } dec %Balls } if (%RTime) { return %RTime %RBall } } menu @b2 { mouse { tokenize 32 $hget(@B2,Ball.16) var %x = $1 , %y = $2 , %vx = $3 , %vy = $4 , %s = $hget(@B2,Table.Scale) , %Motion = $hget(@B2,Motion) , %Break = $hget(@B2,Table.Break) , %Scratch = $hget(@B2,Table.Scratch) if (!%Motion) { if ($Mouse.key & 1) { return } else { var %w = $window(@b2).dw , %h = $window(@B2).dh , %hw = %w / 2 , %hh = %h / 2 var %mx = $calc($mouse.x - %hw) / %s , %my = $calc($mouse.y - %hh) / %s var %dx = %mx - %x , %dy = %my - %y , %mag = $hypot(%dx,%dy) var %dx = %dx / %mag , %dy = %dy / %mag if (!%scratch) { hadd -m @B2 Ball.16 %x %y %dx %dy } else { tokenize 32 $hget(@B2,Table.PlayableSurfaceSize) var %sw = $1 - 2.25 , %sh = $2 - 2.25 , %SSPx = %sw / -2 , %SSpy = %sh / -2 if (%break && $inrect(%mx,%my,%SSpx,%SSPy,%Sw,%Sh)) { hadd -m @B2 Ball.16 %mx %my 0 0 } else { var %sw = $1 , %sh = $2 - 2.25 , %SSPx = $calc(%sw / 4 + 1.125) , %SSpy = %sh / -2 var %sw = $calc(%sw / 4 - 1.125) if (!%break && $inrect(%mx,%my,%SSpx,%SSPy,%Sw,%Sh)) { hadd -m @B2 Ball.16 %mx %my 0 0 } } } tokenize 32 $B2.ClosestBallCollision(16) if ($0 = 2) { hadd -m @B2 Closest.Ball $1- } else { hdel -w @B2 Closest.Ball tokenize 32 $B2.ClosestRailCollision(16) if ($0 = 3) { hadd -m @B2 Closest.Rail $1- } else { hdel -w @B2 Closest.Rail } } } } } uclick { tokenize 32 $hget(@B2,Ball.16) $hget(@B2,Table.Scale) $hget(@B2,Motion) $hget(@B2,Table.Break) $hget(@B2,Table.Scratch) var %x = $1 , %y = $2 , %vx = $3 , %vy = $4 , %s = $5 , %Motion = $6 , %break = $7 , %scratch = $8 var %w = $window(@b2).dw , %h = $window(@B2).dh , %hw = %w / 2 , %hh = %h / 2 if (!%Motion) { if (!%Scratch) { tokenize 32 $click(@B2,$click(@B2,0)) if ($0 = 2) { var %mx = $calc($1 - %hw) / %s , %my = $calc($2 - %hh) / %s , %mmag = $iif($hypot($calc($1 - $mouse.x),$calc($2 - $mouse.y)) > 100,100,$v1) / 1000 } else { var %mx = $calc($mouse.x - %hw) / %s , %my = $calc($mouse.y - %hh) / %s } var %dx = %mx - %x , %dy = %my - %y , %mag = $hypot(%dx,%dy) var %dx = %dx / %mag , %dy = %dy / %mag hadd -m @B2 Ball.16 %x %y $calc(%dx * 0.7 * %mmag) $calc(%dy * 0.7 * %mmag) hadd -m @B2 Motion $biton(%Motion,16) } else { var %mx = $calc($mouse.x - %hw) / %s , %my = $calc($mouse.y - %hh) / %s tokenize 32 $hget(@B2,Table.PlayableSurfaceSize) var %Gw = $calc($1 / 16) , %Gh = $calc($2 / 8) , %BGw = $calc($1 / 32) , %BGh = $calc($2 / 16) var %sw = $1 - 2.25 , %sh = $2 - 2.25 , %SSPx = %sw / -2 , %SSpy = %sh / -2 if (%break && $inrect(%mx,%my,%SSpx,%SSPy,%Sw,%Sh)) { hadd -m @B2 Ball.16 %mx %my 0 0 var %mgx = $calc(%mx // %BGw + 17) , %mgy = $calc(%my // %BGh + 9) var %bin = $base($B2.Grid9x9(%mgx,%mgy),10,2) , %len = $len(%bin) , %match = 1 while ($pos(%bin,1,%match)) { var %c = $calc(%len - $v1 +1) , %CBall = Ball. $+ %c tokenize 32 $hget(@B2,%CBall) var %cx = $1 , %cy = $2 , %cvx = $3 , %cvy = $4 var %diffx = %cx - %mx , %diffy = %cy - %my , %mag = $calc(%diffx ^ 2 + %diffy ^ 2) if (%mag < 5.0625) { return } inc %match } hdel -w @B2 Table.Scratch } else { var %sw = $1 , %sh = $2 - 2.25 , %SSPx = $calc(%sw / 4 + 1.125) , %SSpy = %sh / -2 var %sw = $calc(%sw / 4 - 1.125) if (!%break && $inrect(%mx,%my,%SSpx,%SSPy,%Sw,%Sh)) { hadd -m @B2 Ball.16 %mx %my 0 0 var %mgx = $calc(%mx // %BGw + 17) , %mgy = $calc(%my // %BGh + 9) var %bin = $base($B2.Grid9x9(%mgx,%mgy),10,2) , %len = $len(%bin) , %match = 1 while ($pos(%bin,1,%match)) { var %c = $calc(%len - $v1 +1) , %CBall = Ball. $+ %c tokenize 32 $hget(@B2,%CBall) var %cx = $1 , %cy = $2 , %cvx = $3 , %cvy = $4 var %diffx = %cx - %mx , %diffy = %cy - %my , %mag = $calc(%diffx ^ 2 + %diffy ^ 2) if (%mag < 5.0625) { return } inc %match } hdel -w @B2 Table.Scratch } } } } clear -c @B2 } New Game:b2 $hget(@B2,Table.Scale) $hget(@B2,Table.Size) $hget(@B2,Table.Game) - New Table .9-Ball ..6 Foot Table:b2 $hget(@B2,Table.Scale) 6 ..7 Foot Table:b2 $hget(@B2,Table.Scale) 7 ..8 Foot Table:b2 $hget(@B2,Table.Scale) 8 ..8.5 Foot Table:b2 $hget(@B2,Table.Scale) 8.5 ..9 Foot Table:b2 $hget(@B2,Table.Scale) 9 .8-Ball ..6 Foot Table:b2 $hget(@B2,Table.Scale) 6 8 ..7 Foot Table:b2 $hget(@B2,Table.Scale) 7 8 ..8 Foot Table:b2 $hget(@B2,Table.Scale) 8 8 ..8.5 Foot Table:b2 $hget(@B2,Table.Scale) 8.5 8 ..9 Foot Table:b2 $hget(@B2,Table.Scale) 9 8 - Table Scale .9:hadd -m @B2 Table.Scale 9 .12:hadd -m @B2 Table.Scale 12 .15:hadd -m @B2 Table.Scale 15 .18:hadd -m @B2 Table.Scale 18 .21:hadd -m @B2 Table.Scale 21 } on *:close:@B2: { .timer $+ $target off | hfree -w $target | window -c $target $+ .Surface }
0
Except for missing things like 'english' spin, this plays very similar to the pool game at the former 'Yahoo games'. Glitches mentioned in the description are few/far between, though I did once have a cueball not reset after a scratch, where it eventually came dribbling out of the pocket. There's no menu for this game, but you can easily add it like:
menu status {
Play Billiards!:b2
}
Suggestions for improvements, include a $style check for the current setting when browsing the B2 menu.
Also have a cheatsheet in the menu to remind us of the ball sequence in 9-ball.
Also an option to remove the logo in the middle of the board
Have an option to remember the prior setting, including the location/angle/power of the last shot. This could permit to either save the in-progress game to disk, or add an Undo feature. This would also allow people to submit bug reports that could be reproduced.
Also have a game editor which would allow creating a table layout for testing trick shots.