#!/bin/sh -e # the next line restarts using wish \ exec `which wish | tail -1` "$0" "$@" ############################################################## ## # An animated version of "99 Bottles" ## # Prints the song and shows how it's done. ## # 2007 by "Germanium Diode" ## # Written to amuse ... No Copyright ## # Version 2 : added shelves - and some badly needed comments ## # and the party will never end ## # settings # canvas widht/height ; shelve's width ; spacing of bottles set wi 990; set he 540; set ww 330; set dx 30; set dy 60 # stepping speed of animation in milliseconds set delay 40; # bottle cap falling set cap(g) 1.2; # "gravity" # circular movement (when passing the bottle around) set cir(x0) 470; set cir(y0) 210; set cir(ra) 140 set cir(da) [expr atan(1.0)/4.0]; # delta angle # empty bottle thrown away set em(g) 2.5; set em(nn) 20; # "gravity"; steps # recycle & refill set re(after) 250; set re(nn) 20; # wait cycles; steps set re(x0) 825; set re(y0) 213; # refill from coordinate ## # the shape of things to come set sbottle {11 3 11 20 5 30 5 57 25 57 25 30 19 20 19 3} set scap {10 5 10 2 20 2 20 5} set sfull {12 10 12 21 6 31 6 56 24 56 24 31 18 21 18 10} set ebottle {3 11 20 11 30 5 57 5 57 25 30 25 20 19 3 19} set ecap {10 2 10 5 20 5 20 2} set bcap {20 10 20 4 40 4 40 10} set bbottle {22 6 22 40 10 60 10 114 50 114 50 60 38 40 38 6} set bf(1) {24 20 24 42 12 62 12 112 48 112 48 62 36 42 36 20} set bf(2) {24 42 12 62 12 112 48 112 48 62 36 42} set bf(3) {12 62 12 112 48 112 48 62} set bf(4) {12 72 12 112 48 112 48 72} set bf(5) {12 82 12 112 48 112 48 82} set bf(6) {12 92 12 112 48 112 48 92} set bf(7) {12 102 12 112 48 112 48 102} set bf(8) {12 110 12 112 48 112 48 110} set vat {-59 -99 -59 99 59 99 59 -99} ## # common routines proc oline {o x y w c t} {.c move [.c create line $o -width $w -tag $t -fill $c] $x $y} proc ofill {o x y c t} {.c move [.c create polygon $o -tag $t -fill $c] $x $y} proc putn {str} {puts -nonewline stdout $str; flush stdout} proc add {a_ b} {upvar $a_ a; set a [expr $a+$b]} proc bottles {} { global bottles if {$bottles > 1} {return "$bottles bottles"} return "one bottle" } ## # bottle to coordinate / pack bottle on shelve proc bot2xy {b x_ y_} { global dx dy upvar $x_ x; upvar $y_ y set bb [expr 99-$b] set x [expr ($bb % 11) * $dx] set y [expr ($bb / 11) * $dy] } proc place_bottle {b x y} { global sbottle scap sfull color oline $sbottle $x $y 2 darkgreen b${b} oline $scap $x $y 2 black b${b} ofill $sfull $x $y $color b${b} } proc shelve_bottle {b} { bot2xy $b x y; place_bottle $b $x $y } ## # if its lager, we'll get a head proc bottle_head {tag} { global beer; if {$beer != {lager}} {return} set coords [.c coords $tag] set x0 [lindex $coords 0] set x1 [lindex $coords end-1] set y [lindex $coords 1] .c create line $x0 $y $x1 $y -width 4 -fill white -tag $tag } ## # calculate parameters for straight line animation # x/y to y/x "velocity", calculated: count, dx, dy proc straight {x0 y0 x1 y1 v cnt_ mdx_ mdy_} { upvar $cnt_ cnt upvar $mdx_ mdx upvar $mdy_ mdy set dx [expr double($x1-$x0)] set dy [expr double($y1-$y0)] set cnt [expr int(sqrt($dx*$dx+$dy*$dy)/$v+0.5)] set mdx [expr $dx/double($cnt)] set mdy [expr $dy/double($cnt)] } ## # calculate parameters for "ballistic" curve animation # x/y to y/x, steps, "gravity", calculated: initial dx, dy proc ballistic {x0 y0 x1 y1 cnt g dx_ dy_} { upvar $dx_ dx; upvar $dy_ dy set dx [expr ($x1-$x0)/$cnt] set dy [expr ($y1-$y0)/$cnt-$g*