goldberg.tcl 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833
  1. ##+#################################################################
  2. #
  3. # TkGoldberg.tcl
  4. # by Keith Vetter, March 13, 2003
  5. #
  6. # "Man will always find a difficult means to perform a simple task"
  7. # Rube Goldberg
  8. #
  9. # Reproduced here with permission.
  10. #
  11. ##+#################################################################
  12. #
  13. # Keith Vetter 2003-03-21: this started out as a simple little program
  14. # but was so much fun that it grew and grew. So I apologize about the
  15. # size but I just couldn't resist sharing it.
  16. #
  17. # This is a whizzlet that does a Rube Goldberg type animation, the
  18. # design of which comes from an New Years e-card from IncrediMail.
  19. # That version had nice sound effects which I eschewed. On the other
  20. # hand, that version was in black and white (actually dark blue and
  21. # light blue) and this one is fully colorized.
  22. #
  23. # One thing I learned from this project is that drawing filled complex
  24. # objects on a canvas is really hard. More often than not I had to
  25. # draw each item twice--once with the desired fill color but no
  26. # outline, and once with no fill but with the outline. Another trick
  27. # is erasing by drawing with the background color. Having a flood fill
  28. # command would have been extremely helpful.
  29. #
  30. # Two wiki pages were extremely helpful: Drawing rounded rectangles
  31. # which I generalized into Drawing rounded polygons, and regular
  32. # polygons which allowed me to convert ovals and arcs into polygons
  33. # which could then be rotated (see Canvas Rotation). I also wrote
  34. # Named Colors to aid in the color selection.
  35. #
  36. # I could comment on the code, but it's just 26 state machines with
  37. # lots of canvas create and move calls.
  38. if {![info exists widgetDemo]} {
  39. error "This script should be run from the \"widget\" demo."
  40. }
  41. package require Tk
  42. set w .goldberg
  43. catch {destroy $w}
  44. toplevel $w
  45. wm title $w "Tk Goldberg (demonstration)"
  46. wm iconname $w "goldberg"
  47. wm resizable $w 0 0
  48. #positionWindow $w
  49. label $w.msg -font {Arial 10} -wraplength 4i -justify left -text "This is a\
  50. demonstration of just how complex you can make your animations\
  51. become. Click the ball to start things moving!\n\n\"Man will always\
  52. find a difficult means to perform a simple task\"\n - Rube Goldberg"
  53. pack $w.msg -side top
  54. ###--- End of Boilerplate ---###
  55. # Ensure that this this is an array
  56. array set animationCallbacks {}
  57. bind $w <Destroy> {
  58. if {"%W" eq [winfo toplevel %W]} {
  59. unset S C speed
  60. }
  61. }
  62. set S(title) "Tk Goldberg"
  63. set S(speed) 5
  64. set S(cnt) 0
  65. set S(message) "\\nWelcome\\nto\\nTcl/Tk"
  66. array set speed {1 10 2 20 3 50 4 80 5 100 6 150 7 200 8 300 9 400 10 500}
  67. set MSTART 0; set MGO 1; set MPAUSE 2; set MSSTEP 3; set MBSTEP 4; set MDONE 5
  68. set S(mode) $::MSTART
  69. # Colors for everything
  70. set C(fg) black
  71. set C(bg) gray75
  72. set C(bg) cornflowerblue
  73. set C(0) white; set C(1a) darkgreen; set C(1b) yellow
  74. set C(2) red; set C(3a) green; set C(3b) darkblue
  75. set C(4) $C(fg); set C(5a) brown; set C(5b) white
  76. set C(6) magenta; set C(7) green; set C(8) $C(fg)
  77. set C(9) blue4; set C(10a) white; set C(10b) cyan
  78. set C(11a) yellow; set C(11b) mediumblue; set C(12) tan2
  79. set C(13a) yellow; set C(13b) red; set C(14) white
  80. set C(15a) green; set C(15b) yellow; set C(16) gray65
  81. set C(17) \#A65353; set C(18) $C(fg); set C(19) gray50
  82. set C(20) cyan; set C(21) gray65; set C(22) $C(20)
  83. set C(23a) blue; set C(23b) red; set C(23c) yellow
  84. set C(24a) red; set C(24b) white;
  85. proc DoDisplay {w} {
  86. global S C
  87. ttk::frame $w.ctrl -relief ridge -borderwidth 2 -padding 5
  88. pack [frame $w.screen -bd 2 -relief raised] \
  89. -side left -fill both -expand 1
  90. canvas $w.c -width 860 -height 730 -bg $C(bg) -highlightthickness 0
  91. $w.c config -scrollregion {0 0 1000 1000} ;# Kludge: move everything up
  92. $w.c yview moveto .05
  93. pack $w.c -in $w.screen -side top -fill both -expand 1
  94. bind $w.c <Button-3> [list $w.pause invoke]
  95. bind $w.c <Destroy> {
  96. after cancel $animationCallbacks(goldberg)
  97. unset animationCallbacks(goldberg)
  98. }
  99. DoCtrlFrame $w
  100. DoDetailFrame $w
  101. if {[tk windowingsystem] ne "aqua"} {
  102. ttk::button $w.show -text "\u00bb" -command [list ShowCtrl $w] -width 2
  103. } else {
  104. button $w.show -text "\u00bb" -command [list ShowCtrl $w] -width 2 -highlightbackground $C(bg)
  105. }
  106. place $w.show -in $w.c -relx 1 -rely 0 -anchor ne
  107. update
  108. }
  109. proc DoCtrlFrame {w} {
  110. global S
  111. ttk::button $w.start -text "Start" -command [list DoButton $w 0]
  112. ttk::checkbutton $w.pause -text "Pause" -command [list DoButton $w 1] \
  113. -variable S(pause)
  114. ttk::button $w.step -text "Single Step" -command [list DoButton $w 2]
  115. ttk::button $w.bstep -text "Big Step" -command [list DoButton $w 4]
  116. ttk::button $w.reset -text "Reset" -command [list DoButton $w 3]
  117. ttk::labelframe $w.details
  118. raise $w.details
  119. set S(details) 0
  120. ttk::checkbutton $w.details.cb -text "Details" -variable S(details)
  121. ttk::labelframe $w.message -text "Message"
  122. ttk::entry $w.message.e -textvariable S(message) -justify center
  123. ttk::labelframe $w.speed -text "Speed: 0"
  124. ttk::scale $w.speed.scale -orient h -from 1 -to 10 -variable S(speed)
  125. ttk::button $w.about -text About -command [list About $w]
  126. grid $w.start -in $w.ctrl -row 0 -sticky ew
  127. grid rowconfigure $w.ctrl 1 -minsize 10
  128. grid $w.pause -in $w.ctrl -row 2 -sticky ew
  129. grid $w.step -in $w.ctrl -sticky ew -pady 2
  130. grid $w.bstep -in $w.ctrl -sticky ew
  131. grid $w.reset -in $w.ctrl -sticky ew -pady 2
  132. grid rowconfigure $w.ctrl 10 -minsize 18
  133. grid $w.details -in $w.ctrl -row 11 -sticky ew
  134. grid rowconfigure $w.ctrl 11 -minsize 20
  135. $w.details configure -labelwidget $w.details.cb
  136. grid [ttk::frame $w.details.b -height 1] ;# Work around minor bug
  137. raise $w.details
  138. raise $w.details.cb
  139. grid rowconfigure $w.ctrl 50 -weight 1
  140. trace variable ::S(mode) w [list ActiveGUI $w]
  141. trace variable ::S(details) w [list ActiveGUI $w]
  142. trace variable ::S(speed) w [list ActiveGUI $w]
  143. grid $w.message -in $w.ctrl -row 98 -sticky ew -pady 5
  144. grid $w.message.e -sticky nsew
  145. grid $w.speed -in $w.ctrl -row 99 -sticky ew -pady {0 5}
  146. pack $w.speed.scale -fill both -expand 1
  147. grid $w.about -in $w.ctrl -row 100 -sticky ew
  148. bind $w.reset <Button-3> {set S(mode) -1} ;# Debugging
  149. ## See Code / Dismiss buttons hack!
  150. set btns [addSeeDismiss $w.ctrl.buttons $w]
  151. grid [ttk::separator $w.ctrl.sep] -sticky ew -pady 4
  152. set i 0
  153. foreach b [winfo children $btns] {
  154. if {[winfo class $b] eq "TButton"} {
  155. grid [set b2 [ttk::button $w.ctrl.b[incr i]]] -sticky ew
  156. foreach b3 [$b configure] {
  157. set b3 [lindex $b3 0]
  158. # Some options are read-only; ignore those errors
  159. catch {$b2 configure $b3 [$b cget $b3]}
  160. }
  161. }
  162. }
  163. destroy $btns
  164. }
  165. proc DoDetailFrame {w} {
  166. set w2 $w.details.f
  167. ttk::frame $w2
  168. set bd 2
  169. ttk::label $w2.l -textvariable S(cnt) -background white
  170. grid $w2.l - - - -sticky ew -row 0
  171. for {set i 1} {1} {incr i} {
  172. if {[info procs "Move$i"] eq ""} break
  173. ttk::label $w2.l$i -text $i -anchor e -width 2 -background white
  174. ttk::label $w2.ll$i -textvariable STEP($i) -width 5 -background white
  175. set row [expr {($i + 1) / 2}]
  176. set col [expr {(($i + 1) & 1) * 2}]
  177. grid $w2.l$i -sticky ew -row $row -column $col
  178. grid $w2.ll$i -sticky ew -row $row -column [incr col]
  179. }
  180. grid columnconfigure $w2 1 -weight 1
  181. }
  182. # Map or unmap the ctrl window
  183. proc ShowCtrl {w} {
  184. if {[winfo ismapped $w.ctrl]} {
  185. pack forget $w.ctrl
  186. $w.show config -text "\u00bb"
  187. } else {
  188. pack $w.ctrl -side right -fill both -ipady 5
  189. $w.show config -text "\u00ab"
  190. }
  191. }
  192. proc DrawAll {w} {
  193. ResetStep
  194. $w.c delete all
  195. for {set i 0} {1} {incr i} {
  196. set p "Draw$i"
  197. if {[info procs $p] eq ""} break
  198. $p $w
  199. }
  200. }
  201. proc ActiveGUI {w var1 var2 op} {
  202. global S MGO MSTART MDONE
  203. array set z {0 disabled 1 normal}
  204. set m $S(mode)
  205. set S(pause) [expr {$m == 2}]
  206. $w.start config -state $z([expr {$m != $MGO}])
  207. $w.pause config -state $z([expr {$m != $MSTART && $m != $MDONE}])
  208. $w.step config -state $z([expr {$m != $MGO && $m != $MDONE}])
  209. $w.bstep config -state $z([expr {$m != $MGO && $m != $MDONE}])
  210. $w.reset config -state $z([expr {$m != $MSTART}])
  211. if {$S(details)} {
  212. grid $w.details.f -sticky ew
  213. } else {
  214. grid forget $w.details.f
  215. }
  216. set S(speed) [expr {round($S(speed))}]
  217. $w.speed config -text "Speed: $S(speed)"
  218. }
  219. proc Start {} {
  220. global S MGO
  221. set S(mode) $MGO
  222. }
  223. proc DoButton {w what} {
  224. global S MDONE MGO MSSTEP MBSTEP MPAUSE
  225. if {$what == 0} { ;# Start
  226. if {$S(mode) == $MDONE} {
  227. Reset $w
  228. }
  229. set S(mode) $MGO
  230. } elseif {$what == 1} { ;# Pause
  231. set S(mode) [expr {$S(pause) ? $MPAUSE : $MGO}]
  232. } elseif {$what == 2} { ;# Step
  233. set S(mode) $MSSTEP
  234. } elseif {$what == 3} { ;# Reset
  235. Reset $w
  236. } elseif {$what == 4} { ;# Big step
  237. set S(mode) $MBSTEP
  238. }
  239. }
  240. proc Go {w {who {}}} {
  241. global S speed animationCallbacks MGO MPAUSE MSSTEP MBSTEP
  242. set now [clock clicks -milliseconds]
  243. catch {after cancel $animationCallbacks(goldberg)}
  244. if {$who ne ""} { ;# Start here for debugging
  245. set S(active) $who;
  246. set S(mode) $MGO
  247. }
  248. if {$S(mode) == -1} return ;# Debugging
  249. set n 0
  250. if {$S(mode) != $MPAUSE} { ;# Not paused
  251. set n [NextStep $w] ;# Do the next move
  252. }
  253. if {$S(mode) == $MSSTEP} { ;# Single step
  254. set S(mode) $MPAUSE
  255. }
  256. if {$S(mode) == $MBSTEP && $n} { ;# Big step
  257. set S(mode) $MSSTEP
  258. }
  259. set elapsed [expr {[clock click -milliseconds] - $now}]
  260. set delay [expr {$speed($S(speed)) - $elapsed}]
  261. if {$delay <= 0} {
  262. set delay 1
  263. }
  264. set animationCallbacks(goldberg) [after $delay [list Go $w]]
  265. }
  266. # NextStep: drives the next step of the animation
  267. proc NextStep {w} {
  268. global S MSTART MDONE
  269. set rval 0 ;# Return value
  270. if {$S(mode) != $MSTART && $S(mode) != $MDONE} {
  271. incr S(cnt)
  272. }
  273. set alive {}
  274. foreach {who} $S(active) {
  275. set n ["Move$who" $w]
  276. if {$n & 1} { ;# This guy still alive
  277. lappend alive $who
  278. }
  279. if {$n & 2} { ;# Next guy is active
  280. lappend alive [expr {$who + 1}]
  281. set rval 1
  282. }
  283. if {$n & 4} { ;# End of puzzle flag
  284. set S(mode) $MDONE ;# Done mode
  285. set S(active) {} ;# No more animation
  286. return 1
  287. }
  288. }
  289. set S(active) $alive
  290. return $rval
  291. }
  292. proc About {w} {
  293. set msg "$::S(title)\nby Keith Vetter, March 2003\n(Reproduced by kind\
  294. permission of the author)\n\n\"Man will always find a difficult\
  295. means to perform a simple task.\"\nRube Goldberg"
  296. tk_messageBox -parent $w -message $msg -title About
  297. }
  298. ################################################################
  299. #
  300. # All the drawing and moving routines
  301. #
  302. # START HERE! banner
  303. proc Draw0 {w} {
  304. set color $::C(0)
  305. set xy {579 119}
  306. $w.c create text $xy -text "START HERE!" -fill $color -anchor w \
  307. -tag I0 -font {{Times Roman} 12 italic bold}
  308. set xy {719 119 763 119}
  309. $w.c create line $xy -tag I0 -fill $color -width 5 -arrow last \
  310. -arrowshape {18 18 5}
  311. $w.c bind I0 <Button-1> Start
  312. }
  313. proc Move0 {w {step {}}} {
  314. set step [GetStep 0 $step]
  315. if {$::S(mode) > $::MSTART} { ;# Start the ball rolling
  316. MoveAbs $w I0 {-100 -100} ;# Hide the banner
  317. return 2
  318. }
  319. set pos {
  320. {673 119} {678 119} {683 119} {688 119}
  321. {693 119} {688 119} {683 119} {678 119}
  322. }
  323. set step [expr {$step % [llength $pos]}]
  324. MoveAbs $w I0 [lindex $pos $step]
  325. return 1
  326. }
  327. # Dropping ball
  328. proc Draw1 {w} {
  329. set color $::C(1a)
  330. set color2 $::C(1b)
  331. set xy {844 133 800 133 800 346 820 346 820 168 844 168 844 133}
  332. $w.c create poly $xy -width 3 -fill $color -outline {}
  333. set xy {771 133 685 133 685 168 751 168 751 346 771 346 771 133}
  334. $w.c create poly $xy -width 3 -fill $color -outline {}
  335. set xy [box 812 122 9]
  336. $w.c create oval $xy -tag I1 -fill $color2 -outline {}
  337. $w.c bind I1 <Button-1> Start
  338. }
  339. proc Move1 {w {step {}}} {
  340. set step [GetStep 1 $step]
  341. set pos {
  342. {807 122} {802 122} {797 123} {793 124} {789 129} {785 153}
  343. {785 203} {785 278 x} {785 367} {810 392} {816 438} {821 503}
  344. {824 585 y} {838 587} {848 593} {857 601} {-100 -100}
  345. }
  346. if {$step >= [llength $pos]} {
  347. return 0
  348. }
  349. set where [lindex $pos $step]
  350. MoveAbs $w I1 $where
  351. if {[lindex $where 2] eq "y"} {
  352. Move15a $w
  353. }
  354. if {[lindex $where 2] eq "x"} {
  355. return 3
  356. }
  357. return 1
  358. }
  359. # Lighting the match
  360. proc Draw2 {w} {
  361. set color red
  362. set color $::C(2)
  363. set xy {750 369 740 392 760 392} ;# Fulcrum
  364. $w.c create poly $xy -fill $::C(fg) -outline $::C(fg)
  365. set xy {628 335 660 383} ;# Strike box
  366. $w.c create rect $xy -fill {} -outline $::C(fg)
  367. for {set y 0} {$y < 3} {incr y} {
  368. set yy [expr {335+$y*16}]
  369. $w.c create bitmap 628 $yy -bitmap gray25 -anchor nw \
  370. -foreground $::C(fg)
  371. $w.c create bitmap 644 $yy -bitmap gray25 -anchor nw \
  372. -foreground $::C(fg)
  373. }
  374. set xy {702 366 798 366} ;# Lever
  375. $w.c create line $xy -fill $::C(fg) -width 6 -tag I2_0
  376. set xy {712 363 712 355} ;# R strap
  377. $w.c create line $xy -fill $::C(fg) -width 3 -tag I2_1
  378. set xy {705 363 705 355} ;# L strap
  379. $w.c create line $xy -fill $::C(fg) -width 3 -tag I2_2
  380. set xy {679 356 679 360 717 360 717 356 679 356} ;# Match stick
  381. $w.c create line $xy -fill $::C(fg) -tag I2_3
  382. #set xy {662 352 680 365} ;# Match head
  383. set xy {
  384. 671 352 677.4 353.9 680 358.5 677.4 363.1 671 365 664.6 363.1
  385. 662 358.5 664.6 353.9
  386. }
  387. $w.c create poly $xy -fill $color -outline $color -tag I2_4
  388. }
  389. proc Move2 {w {step {}}} {
  390. set step [GetStep 2 $step]
  391. set stages {0 0 1 2 0 2 1 0 1 2 0 2 1}
  392. set xy(0) {
  393. 686 333 692 323 682 316 674 309 671 295 668 307 662 318 662 328
  394. 671 336
  395. }
  396. set xy(1) {687 331 698 322 703 295 680 320 668 297 663 311 661 327 671 335}
  397. set xy(2) {
  398. 686 331 704 322 688 300 678 283 678 283 674 298 666 309 660 324
  399. 672 336
  400. }
  401. if {$step >= [llength $stages]} {
  402. $w.c delete I2
  403. return 0
  404. }
  405. if {$step == 0} { ;# Rotate the match
  406. set beta 20
  407. lassign [Anchor $w I2_0 s] Ox Oy ;# Where to pivot
  408. for {set i 0} {[$w.c find withtag I2_$i] ne ""} {incr i} {
  409. RotateItem $w I2_$i $Ox $Oy $beta
  410. }
  411. $w.c create poly -tag I2 -smooth 1 -fill $::C(2) ;# For the flame
  412. return 1
  413. }
  414. $w.c coords I2 $xy([lindex $stages $step])
  415. return [expr {$step == 7 ? 3 : 1}]
  416. }
  417. # Weight and pulleys
  418. proc Draw3 {w} {
  419. set color $::C(3a)
  420. set color2 $::C(3b)
  421. set xy {602 296 577 174 518 174}
  422. foreach {x y} $xy { ;# 3 Pulleys
  423. $w.c create oval [box $x $y 13] -fill $color -outline $::C(fg) \
  424. -width 3
  425. $w.c create oval [box $x $y 2] -fill $::C(fg) -outline $::C(fg)
  426. }
  427. set xy {750 309 670 309} ;# Wall to flame
  428. $w.c create line $xy -tag I3_s -width 3 -fill $::C(fg) -smooth 1
  429. set xy {670 309 650 309} ;# Flame to pulley 1
  430. $w.c create line $xy -tag I3_0 -width 3 -fill $::C(fg)
  431. set xy {650 309 600 309} ;# Flame to pulley 1
  432. $w.c create line $xy -tag I3_1 -width 3 -fill $::C(fg)
  433. set xy {589 296 589 235} ;# Pulley 1 half way to 2
  434. $w.c create line $xy -tag I3_2 -width 3 -fill $::C(fg)
  435. set xy {589 235 589 174} ;# Pulley 1 other half to 2
  436. $w.c create line $xy -width 3 -fill $::C(fg)
  437. set xy {577 161 518 161} ;# Across the top
  438. $w.c create line $xy -width 3 -fill $::C(fg)
  439. set xy {505 174 505 205} ;# Down to weight
  440. $w.c create line $xy -tag I3_w -width 3 -fill $::C(fg)
  441. # Draw the weight as 2 circles, two rectangles and 1 rounded rectangle
  442. set xy {515 207 495 207}
  443. foreach {x1 y1 x2 y2} $xy {
  444. $w.c create oval [box $x1 $y1 6] -tag I3_ -fill $color2 \
  445. -outline $color2
  446. $w.c create oval [box $x2 $y2 6] -tag I3_ -fill $color2 \
  447. -outline $color2
  448. incr y1 -6; incr y2 6
  449. $w.c create rect $x1 $y1 $x2 $y2 -tag I3_ -fill $color2 \
  450. -outline $color2
  451. }
  452. set xy {492 220 518 263}
  453. set xy [RoundRect $w $xy 15]
  454. $w.c create poly $xy -smooth 1 -tag I3_ -fill $color2 -outline $color2
  455. set xy {500 217 511 217}
  456. $w.c create line $xy -tag I3_ -fill $color2 -width 10
  457. set xy {502 393 522 393 522 465} ;# Bottom weight target
  458. $w.c create line $xy -tag I3__ -fill $::C(fg) -join miter -width 10
  459. }
  460. proc Move3 {w {step {}}} {
  461. set step [GetStep 3 $step]
  462. set pos {{505 247} {505 297} {505 386.5} {505 386.5}}
  463. set rope(0) {750 309 729 301 711 324 690 300}
  464. set rope(1) {750 309 737 292 736 335 717 315 712 320}
  465. set rope(2) {750 309 737 309 740 343 736 351 725 340}
  466. set rope(3) {750 309 738 321 746 345 742 356}
  467. if {$step >= [llength $pos]} {
  468. return 0
  469. }
  470. $w.c delete "I3_$step" ;# Delete part of the rope
  471. MoveAbs $w I3_ [lindex $pos $step] ;# Move weight down
  472. $w.c coords I3_s $rope($step) ;# Flapping rope end
  473. $w.c coords I3_w [concat 505 174 [lindex $pos $step]]
  474. if {$step == 2} {
  475. $w.c move I3__ 0 30
  476. return 2
  477. }
  478. return 1
  479. }
  480. # Cage and door
  481. proc Draw4 {w} {
  482. set color $::C(4)
  483. lassign {527 356 611 464} x0 y0 x1 y1
  484. for {set y $y0} {$y <= $y1} {incr y 12} { ;# Horizontal bars
  485. $w.c create line $x0 $y $x1 $y -fill $color -width 1
  486. }
  487. for {set x $x0} {$x <= $x1} {incr x 12} { ;# Vertical bars
  488. $w.c create line $x $y0 $x $y1 -fill $color -width 1
  489. }
  490. set xy {518 464 518 428} ;# Swing gate
  491. $w.c create line $xy -tag I4 -fill $color -width 3
  492. }
  493. proc Move4 {w {step {}}} {
  494. set step [GetStep 4 $step]
  495. set angles {-10 -20 -30 -30}
  496. if {$step >= [llength $angles]} {
  497. return 0
  498. }
  499. RotateItem $w I4 518 464 [lindex $angles $step]
  500. $w.c raise I4
  501. return [expr {$step == 3 ? 3 : 1}]
  502. }
  503. # Mouse
  504. proc Draw5 {w} {
  505. set color $::C(5a)
  506. set color2 $::C(5b)
  507. set xy {377 248 410 248 410 465 518 465} ;# Mouse course
  508. lappend xy 518 428 451 428 451 212 377 212
  509. $w.c create poly $xy -fill $color2 -outline $::C(fg) -width 3
  510. set xy {
  511. 534.5 445.5 541 440 552 436 560 436 569 440 574 446 575 452 574 454
  512. 566 456 554 456 545 456 537 454 530 452
  513. }
  514. $w.c create poly $xy -tag {I5 I5_0} -fill $color
  515. set xy {573 452 592 458 601 460 613 456} ;# Tail
  516. $w.c create line $xy -tag {I5 I5_1} -fill $color -smooth 1 -width 3
  517. set xy [box 540 446 2] ;# Eye
  518. set xy {540 444 541 445 541 447 540 448 538 447 538 445}
  519. #.c create oval $xy -tag {I5 I5_2} -fill $::C(bg) -outline {}
  520. $w.c create poly $xy -tag {I5 I5_2} -fill $::C(bg) -outline {} -smooth 1
  521. set xy {538 454 535 461} ;# Front leg
  522. $w.c create line $xy -tag {I5 I5_3} -fill $color -width 2
  523. set xy {566 455 569 462} ;# Back leg
  524. $w.c create line $xy -tag {I5 I5_4} -fill $color -width 2
  525. set xy {544 455 545 460} ;# 2nd front leg
  526. $w.c create line $xy -tag {I5 I5_5} -fill $color -width 2
  527. set xy {560 455 558 460} ;# 2nd back leg
  528. $w.c create line $xy -tag {I5 I5_6} -fill $color -width 2
  529. }
  530. proc Move5 {w {step {}}} {
  531. set step [GetStep 5 $step]
  532. set pos {
  533. {553 452} {533 452} {513 452} {493 452} {473 452}
  534. {463 442 30} {445.5 441.5 30} {425.5 434.5 30} {422 414} {422 394}
  535. {422 374} {422 354} {422 334} {422 314} {422 294}
  536. {422 274 -30} {422 260.5 -30 x} {422.5 248.5 -28} {425 237}
  537. }
  538. if {$step >= [llength $pos]} {
  539. return 0
  540. }
  541. lassign [lindex $pos $step] x y beta next
  542. MoveAbs $w I5 [list $x $y]
  543. if {$beta ne ""} {
  544. lassign [Centroid $w I5_0] Ox Oy
  545. foreach id {0 1 2 3 4 5 6} {
  546. RotateItem $w I5_$id $Ox $Oy $beta
  547. }
  548. }
  549. if {$next eq "x"} {
  550. return 3
  551. }
  552. return 1
  553. }
  554. # Dropping gumballs
  555. array set XY6 {
  556. -1 {366 207} -2 {349 204} -3 {359 193} -4 {375 192} -5 {340 190}
  557. -6 {349 177} -7 {366 177} -8 {380 176} -9 {332 172} -10 {342 161}
  558. -11 {357 164} -12 {372 163} -13 {381 149} -14 {364 151} -15 {349 146}
  559. -16 {333 148} 0 {357 219}
  560. 1 {359 261} 2 {359 291} 3 {359 318} 4 {361 324} 5 {365 329} 6 {367 334}
  561. 7 {367 340} 8 {366 346} 9 {364 350} 10 {361 355} 11 {359 370} 12 {359 391}
  562. 13,0 {360 456} 13,1 {376 456} 13,2 {346 456} 13,3 {330 456}
  563. 13,4 {353 444} 13,5 {368 443} 13,6 {339 442} 13,7 {359 431}
  564. 13,8 {380 437} 13,9 {345 428} 13,10 {328 434} 13,11 {373 424}
  565. 13,12 {331 420} 13,13 {360 417} 13,14 {345 412} 13,15 {376 410}
  566. 13,16 {360 403}
  567. }
  568. proc Draw6 {w} {
  569. set color $::C(6)
  570. set xy {324 130 391 204} ;# Ball holder
  571. set xy [RoundRect $w $xy 10]
  572. $w.c create poly $xy -smooth 1 -outline $::C(fg) -width 3 -fill $color
  573. set xy {339 204 376 253} ;# Below the ball holder
  574. $w.c create rect $xy -fill {} -outline $::C(fg) -width 3 -fill $color \
  575. -tag I6c
  576. set xy [box 346 339 28]
  577. $w.c create oval $xy -fill $color -outline {} ;# Rotor
  578. $w.c create arc $xy -outline $::C(fg) -width 2 -style arc \
  579. -start 80 -extent 205
  580. $w.c create arc $xy -outline $::C(fg) -width 2 -style arc \
  581. -start -41 -extent 85
  582. set xy [box 346 339 15] ;# Center of rotor
  583. $w.c create oval $xy -outline $::C(fg) -fill $::C(fg) -tag I6m
  584. set xy {352 312 352 254 368 254 368 322} ;# Top drop to rotor
  585. $w.c create poly $xy -fill $color -outline {}
  586. $w.c create line $xy -fill $::C(fg) -width 2
  587. set xy {353 240 367 300} ;# Poke bottom hole
  588. $w.c create rect $xy -fill $color -outline {}
  589. set xy {341 190 375 210} ;# Poke another hole
  590. $w.c create rect $xy -fill $color -outline {}
  591. set xy {368 356 368 403 389 403 389 464 320 464 320 403 352 403 352 366}
  592. $w.c create poly $xy -fill $color -outline {} -width 2 ;# Below rotor
  593. $w.c create line $xy -fill $::C(fg) -width 2
  594. set xy [box 275 342 7] ;# On/off rotor
  595. $w.c create oval $xy -outline $::C(fg) -fill $::C(fg)
  596. set xy {276 334 342 325} ;# Fan belt top
  597. $w.c create line $xy -fill $::C(fg) -width 3
  598. set xy {276 349 342 353} ;# Fan belt bottom
  599. $w.c create line $xy -fill $::C(fg) -width 3
  600. set xy {337 212 337 247} ;# What the mouse pushes
  601. $w.c create line $xy -fill $::C(fg) -width 3 -tag I6_
  602. set xy {392 212 392 247}
  603. $w.c create line $xy -fill $::C(fg) -width 3 -tag I6_
  604. set xy {337 230 392 230}
  605. $w.c create line $xy -fill $::C(fg) -width 7 -tag I6_
  606. set who -1 ;# All the balls
  607. set colors {red cyan orange green blue darkblue}
  608. lappend colors {*}$colors {*}$colors
  609. for {set i 0} {$i < 17} {incr i} {
  610. set loc [expr {-1 * $i}]
  611. set color [lindex $colors $i]
  612. $w.c create oval [box {*}$::XY6($loc) 5] -fill $color \
  613. -outline $color -tag I6_b$i
  614. }
  615. Draw6a $w 12 ;# The wheel
  616. }
  617. proc Draw6a {w beta} {
  618. $w.c delete I6_0
  619. lassign {346 339} Ox Oy
  620. for {set i 0} {$i < 4} {incr i} {
  621. set b [expr {$beta + $i * 45}]
  622. lassign [RotateC 28 0 0 0 $b] x y
  623. set xy [list [expr {$Ox+$x}] [expr {$Oy+$y}] \
  624. [expr {$Ox-$x}] [expr {$Oy-$y}]]
  625. $w.c create line $xy -tag I6_0 -fill $::C(fg) -width 2
  626. }
  627. }
  628. proc Move6 {w {step {}}} {
  629. set step [GetStep 6 $step]
  630. if {$step > 62} {
  631. return 0
  632. }
  633. if {$step < 2} { ;# Open gate for balls to drop
  634. $w.c move I6_ -7 0
  635. if {$step == 1} { ;# Poke a hole
  636. set xy {348 226 365 240}
  637. $w.c create rect $xy -fill [$w.c itemcget I6c -fill] -outline {}
  638. }
  639. return 1
  640. }
  641. set s [expr {$step - 1}] ;# Do the gumball drop dance
  642. for {set i 0} {$i <= int(($s-1) / 3)} {incr i} {
  643. set tag "I6_b$i"
  644. if {[$w.c find withtag $tag] eq ""} break
  645. set loc [expr {$s - 3 * $i}]
  646. if {[info exists ::XY6($loc,$i)]} {
  647. MoveAbs $w $tag $::XY6($loc,$i)
  648. } elseif {[info exists ::XY6($loc)]} {
  649. MoveAbs $w $tag $::XY6($loc)
  650. }
  651. }
  652. if {($s % 3) == 1} {
  653. set first [expr {($s + 2) / 3}]
  654. for {set i $first} {1} {incr i} {
  655. set tag "I6_b$i"
  656. if {[$w.c find withtag $tag] eq ""} break
  657. set loc [expr {$first - $i}]
  658. MoveAbs $w $tag $::XY6($loc)
  659. }
  660. }
  661. if {$s >= 3} { ;# Rotate the motor
  662. set idx [expr {$s % 3}]
  663. #Draw6a $w [lindex {12 35 64} $idx]
  664. Draw6a $w [expr {12 + $s * 15}]
  665. }
  666. return [expr {$s == 3 ? 3 : 1}]
  667. }
  668. # On/off switch
  669. proc Draw7 {w} {
  670. set color $::C(7)
  671. set xy {198 306 277 374} ;# Box
  672. $w.c create rect $xy -outline $::C(fg) -width 2 -fill $color -tag I7z
  673. $w.c lower I7z
  674. set xy {275 343 230 349}
  675. $w.c create line $xy -tag I7 -fill $::C(fg) -arrow last \
  676. -arrowshape {23 23 8} -width 6
  677. set xy {225 324} ;# On button
  678. $w.c create oval [box {*}$xy 3] -fill $::C(fg) -outline $::C(fg)
  679. set xy {218 323} ;# On text
  680. set font {{Times Roman} 8}
  681. $w.c create text $xy -text "on" -anchor e -fill $::C(fg) -font $font
  682. set xy {225 350} ;# Off button
  683. $w.c create oval [box {*}$xy 3] -fill $::C(fg) -outline $::C(fg)
  684. set xy {218 349} ;# Off button
  685. $w.c create text $xy -text "off" -anchor e -fill $::C(fg) -font $font
  686. }
  687. proc Move7 {w {step {}}} {
  688. set step [GetStep 7 $step]
  689. set numsteps 30
  690. if {$step > $numsteps} {
  691. return 0
  692. }
  693. set beta [expr {30.0 / $numsteps}]
  694. RotateItem $w I7 275 343 $beta
  695. return [expr {$step == $numsteps ? 3 : 1}]
  696. }
  697. # Electricity to the fan
  698. proc Draw8 {w} {
  699. Sine $w 271 248 271 306 5 8 -tag I8_s -fill $::C(8) -width 3
  700. }
  701. proc Move8 {w {step {}}} {
  702. set step [GetStep 8 $step]
  703. if {$step > 3} {
  704. return 0
  705. }
  706. if {$step == 0} {
  707. Sparkle $w [Anchor $w I8_s s] I8
  708. return 1
  709. } elseif {$step == 1} {
  710. MoveAbs $w I8 [Anchor $w I8_s c]
  711. } elseif {$step == 2} {
  712. MoveAbs $w I8 [Anchor $w I8_s n]
  713. } else {
  714. $w.c delete I8
  715. }
  716. return [expr {$step == 2 ? 3 : 1}]
  717. }
  718. # Fan
  719. proc Draw9 {w} {
  720. set color $::C(9)
  721. set xy {266 194 310 220}
  722. $w.c create oval $xy -outline $color -fill $color
  723. set xy {280 209 296 248}
  724. $w.c create oval $xy -outline $color -fill $color
  725. set xy {288 249 252 249 260 240 280 234 296 234 316 240 324 249 288 249}
  726. $w.c create poly $xy -fill $color -smooth 1
  727. set xy {248 205 265 214 264 205 265 196} ;# Spinner
  728. $w.c create poly $xy -fill $color
  729. set xy {255 206 265 234} ;# Fan blades
  730. $w.c create oval $xy -fill {} -outline $::C(fg) -width 3 -tag I9_0
  731. set xy {255 176 265 204}
  732. $w.c create oval $xy -fill {} -outline $::C(fg) -width 3 -tag I9_0
  733. set xy {255 206 265 220}
  734. $w.c create oval $xy -fill {} -outline $::C(fg) -width 1 -tag I9_1
  735. set xy {255 190 265 204}
  736. $w.c create oval $xy -fill {} -outline $::C(fg) -width 1 -tag I9_1
  737. }
  738. proc Move9 {w {step {}}} {
  739. set step [GetStep 9 $step]
  740. if {$step & 1} {
  741. $w.c itemconfig I9_0 -width 4
  742. $w.c itemconfig I9_1 -width 1
  743. $w.c lower I9_1 I9_0
  744. } else {
  745. $w.c itemconfig I9_0 -width 1
  746. $w.c itemconfig I9_1 -width 4
  747. $w.c lower I9_0 I9_1
  748. }
  749. if {$step == 0} {
  750. return 3
  751. }
  752. return 1
  753. }
  754. # Boat
  755. proc Draw10 {w} {
  756. set color $::C(10a)
  757. set color2 $::C(10b)
  758. set xy {191 230 233 230 233 178 191 178} ;# Sail
  759. $w.c create poly $xy -fill $color -width 3 -outline $::C(fg) -tag I10
  760. set xy [box 209 204 31] ;# Front
  761. $w.c create arc $xy -outline {} -fill $color -style pie \
  762. -start 120 -extent 120 -tag I10
  763. $w.c create arc $xy -outline $::C(fg) -width 3 -style arc \
  764. -start 120 -extent 120 -tag I10
  765. set xy [box 249 204 31] ;# Back
  766. $w.c create arc $xy -outline {} -fill $::C(bg) -width 3 -style pie \
  767. -start 120 -extent 120 -tag I10
  768. $w.c create arc $xy -outline $::C(fg) -width 3 -style arc \
  769. -start 120 -extent 120 -tag I10
  770. set xy {200 171 200 249} ;# Mast
  771. $w.c create line $xy -fill $::C(fg) -width 3 -tag I10
  772. set xy {159 234 182 234} ;# Bow sprit
  773. $w.c create line $xy -fill $::C(fg) -width 3 -tag I10
  774. set xy {180 234 180 251 220 251} ;# Hull
  775. $w.c create line $xy -fill $::C(fg) -width 6 -tag I10
  776. set xy {92 255 221 255} ;# Waves
  777. Sine $w {*}$xy 2 25 -fill $color2 -width 1 -tag I10w
  778. set xy [lrange [$w.c coords I10w] 4 end-4] ;# Water
  779. set xy [concat $xy 222 266 222 277 99 277]
  780. $w.c create poly $xy -fill $color2 -outline $color2
  781. set xy {222 266 222 277 97 277 97 266} ;# Water bottom
  782. $w.c create line $xy -fill $::C(fg) -width 3
  783. set xy [box 239 262 17]
  784. $w.c create arc $xy -outline $::C(fg) -width 3 -style arc \
  785. -start 95 -extent 103
  786. set xy [box 76 266 21]
  787. $w.c create arc $xy -outline $::C(fg) -width 3 -style arc -extent 190
  788. }
  789. proc Move10 {w {step {}}} {
  790. set step [GetStep 10 $step]
  791. set pos {
  792. {195 212} {193 212} {190 212} {186 212} {181 212} {176 212}
  793. {171 212} {166 212} {161 212} {156 212} {151 212} {147 212} {142 212}
  794. {137 212} {132 212 x} {127 212} {121 212} {116 212} {111 212}
  795. }
  796. if {$step >= [llength $pos]} {
  797. return 0
  798. }
  799. set where [lindex $pos $step]
  800. MoveAbs $w I10 $where
  801. if {[lindex $where 2] eq "x"} {
  802. return 3
  803. }
  804. return 1
  805. }
  806. # 2nd ball drop
  807. proc Draw11 {w} {
  808. set color $::C(11a)
  809. set color2 $::C(11b)
  810. set xy {23 264 55 591} ;# Color the down tube
  811. $w.c create rect $xy -fill $color -outline {}
  812. set xy [box 71 460 48] ;# Color the outer loop
  813. $w.c create oval $xy -fill $color -outline {}
  814. set xy {55 264 55 458} ;# Top right side
  815. $w.c create line $xy -fill $::C(fg) -width 3
  816. set xy {55 504 55 591} ;# Bottom right side
  817. $w.c create line $xy -fill $::C(fg) -width 3
  818. set xy [box 71 460 48] ;# Outer loop
  819. $w.c create arc $xy -outline $::C(fg) -width 3 -style arc \
  820. -start 110 -extent -290 -tag I11i
  821. set xy [box 71 460 16] ;# Inner loop
  822. $w.c create oval $xy -outline $::C(fg) -fill {} -width 3 -tag I11i
  823. $w.c create oval $xy -outline $::C(fg) -fill $::C(bg) -width 3
  824. set xy {23 264 23 591} ;# Left side
  825. $w.c create line $xy -fill $::C(fg) -width 3
  826. set xy [box 1 266 23] ;# Top left curve
  827. $w.c create arc $xy -outline $::C(fg) -width 3 -style arc -extent 90
  828. set xy [box 75 235 9] ;# The ball
  829. $w.c create oval $xy -fill $color2 -outline {} -width 3 -tag I11
  830. }
  831. proc Move11 {w {step {}}} {
  832. set step [GetStep 11 $step]
  833. set pos {
  834. {75 235} {70 235} {65 237} {56 240} {46 247} {38 266} {38 296}
  835. {38 333} {38 399} {38 475} {74 496} {105 472} {100 437} {65 423}
  836. {-100 -100} {38 505} {38 527 x} {38 591}
  837. }
  838. if {$step >= [llength $pos]} {
  839. return 0
  840. }
  841. set where [lindex $pos $step]
  842. MoveAbs $w I11 $where
  843. if {[lindex $where 2] eq "x"} {
  844. return 3
  845. }
  846. return 1
  847. }
  848. # Hand
  849. proc Draw12 {w} {
  850. set xy {20 637 20 617 20 610 20 590 40 590 40 590 60 590 60 610 60 610}
  851. lappend xy 60 610 65 620 60 631 ;# Thumb
  852. lappend xy 60 631 60 637 60 662 60 669 52 669 56 669 50 669 50 662 50 637
  853. set y0 637 ;# Bumps for fingers
  854. set y1 645
  855. for {set x 50} {$x > 20} {incr x -10} {
  856. set x1 [expr {$x - 5}]
  857. set x2 [expr {$x - 10}]
  858. lappend xy $x $y0 $x1 $y1 $x2 $y0
  859. }
  860. $w.c create poly $xy -fill $::C(12) -outline $::C(fg) -smooth 1 -tag I12 \
  861. -width 3
  862. }
  863. proc Move12 {w {step {}}} {
  864. set step [GetStep 12 $step]
  865. set pos {{42.5 641 x}}
  866. if {$step >= [llength $pos]} {
  867. return 0
  868. }
  869. set where [lindex $pos $step]
  870. MoveAbs $w I12 $where
  871. if {[lindex $where 2] eq "x"} {
  872. return 3
  873. }
  874. return 1
  875. }
  876. # Fax
  877. proc Draw13 {w} {
  878. set color $::C(13a)
  879. set xy {86 663 149 663 149 704 50 704 50 681 64 681 86 671}
  880. set xy2 {784 663 721 663 721 704 820 704 820 681 806 681 784 671}
  881. set radii {2 9 9 8 5 5 2}
  882. RoundPoly $w.c $xy $radii -width 3 -outline $::C(fg) -fill $color
  883. RoundPoly $w.c $xy2 $radii -width 3 -outline $::C(fg) -fill $color
  884. set xy {56 677}
  885. $w.c create rect [box {*}$xy 4] -fill {} -outline $::C(fg) -width 3 \
  886. -tag I13
  887. set xy {809 677}
  888. $w.c create rect [box {*}$xy 4] -fill {} -outline $::C(fg) -width 3 \
  889. -tag I13R
  890. set xy {112 687} ;# Label
  891. $w.c create text $xy -text "FAX" -fill $::C(fg) \
  892. -font {{Times Roman} 12 bold}
  893. set xy {762 687}
  894. $w.c create text $xy -text "FAX" -fill $::C(fg) \
  895. -font {{Times Roman} 12 bold}
  896. set xy {138 663 148 636 178 636} ;# Paper guide
  897. $w.c create line $xy -smooth 1 -fill $::C(fg) -width 3
  898. set xy {732 663 722 636 692 636}
  899. $w.c create line $xy -smooth 1 -fill $::C(fg) -width 3
  900. Sine $w 149 688 720 688 5 15 -tag I13_s -fill $::C(fg) -width 3
  901. }
  902. proc Move13 {w {step {}}} {
  903. set step [GetStep 13 $step]
  904. set numsteps 7
  905. if {$step == $numsteps+2} {
  906. MoveAbs $w I13_star {-100 -100}
  907. $w.c itemconfig I13R -fill $::C(13b) -width 2
  908. return 2
  909. }
  910. if {$step == 0} { ;# Button down
  911. $w.c delete I13
  912. Sparkle $w {-100 -100} I13_star ;# Create off screen
  913. return 1
  914. }
  915. lassign [Anchor $w I13_s w] x0 y0
  916. lassign [Anchor $w I13_s e] x1 y1
  917. set x [expr {$x0 + ($x1-$x0) * ($step - 1) / double($numsteps)}]
  918. MoveAbs $w I13_star [list $x $y0]
  919. return 1
  920. }
  921. # Paper in fax
  922. proc Draw14 {w} {
  923. set color $::C(14)
  924. set xy {102 661 113 632 130 618} ;# Left paper edge
  925. $w.c create line $xy -smooth 1 -fill $color -width 3 -tag I14L_0
  926. set xy {148 629 125 640 124 662} ;# Right paper edge
  927. $w.c create line $xy -smooth 1 -fill $color -width 3 -tag I14L_1
  928. Draw14a $w L
  929. set xy {
  930. 768.0 662.5 767.991316225 662.433786215 767.926187912 662.396880171
  931. }
  932. $w.c create line $xy -smooth 1 -fill $color -width 3 -tag I14R_0
  933. $w.c lower I14R_0
  934. # NB. these numbers are VERY sensitive, you must start with final size
  935. # and shrink down to get the values
  936. set xy {
  937. 745.947897349 662.428358855 745.997829056 662.452239237 746.0 662.5
  938. }
  939. $w.c create line $xy -smooth 1 -fill $color -width 3 -tag I14R_1
  940. $w.c lower I14R_1
  941. }
  942. proc Draw14a {w side} {
  943. set color $::C(14)
  944. set xy [$w.c coords I14${side}_0]
  945. set xy2 [$w.c coords I14${side}_1]
  946. lassign $xy x0 y0 x1 y1 x2 y2
  947. lassign $xy2 x3 y3 x4 y4 x5 y5
  948. set zz [concat \
  949. $x0 $y0 $x0 $y0 $xy $x2 $y2 $x2 $y2 \
  950. $x3 $y3 $x3 $y3 $xy2 $x5 $y5 $x5 $y5]
  951. $w.c delete I14$side
  952. $w.c create poly $zz -tag I14$side -smooth 1 -fill $color -outline $color \
  953. -width 3
  954. $w.c lower I14$side
  955. }
  956. proc Move14 {w {step {}}} {
  957. set step [GetStep 14 $step]
  958. # Paper going down
  959. set sc [expr {.9 - .05*$step}]
  960. if {$sc < .3} {
  961. $w.c delete I14L
  962. return 0
  963. }
  964. lassign [$w.c coords I14L_0] Ox Oy
  965. $w.c scale I14L_0 $Ox $Oy $sc $sc
  966. lassign [lrange [$w.c coords I14L_1] end-1 end] Ox Oy
  967. $w.c scale I14L_1 $Ox $Oy $sc $sc
  968. Draw14a $w L
  969. # Paper going up
  970. set sc [expr {.35 + .05*$step}]
  971. set sc [expr {1 / $sc}]
  972. lassign [$w.c coords I14R_0] Ox Oy
  973. $w.c scale I14R_0 $Ox $Oy $sc $sc
  974. lassign [lrange [$w.c coords I14R_1] end-1 end] Ox Oy
  975. $w.c scale I14R_1 $Ox $Oy $sc $sc
  976. Draw14a $w R
  977. return [expr {$step == 10 ? 3 : 1}]
  978. }
  979. # Light beam
  980. proc Draw15 {w} {
  981. set color $::C(15a)
  982. set xy {824 599 824 585 820 585 829 585}
  983. $w.c create line $xy -fill $::C(fg) -width 3 -tag I15a
  984. set xy {789 599 836 643}
  985. $w.c create rect $xy -fill $color -outline $::C(fg) -width 3
  986. set xy {778 610 788 632}
  987. $w.c create rect $xy -fill $color -outline $::C(fg) -width 3
  988. set xy {766 617 776 625}
  989. $w.c create rect $xy -fill $color -outline $::C(fg) -width 3
  990. set xy {633 600 681 640}
  991. $w.c create rect $xy -fill $color -outline $::C(fg) -width 3
  992. set xy {635 567 657 599}
  993. $w.c create rect $xy -fill $color -outline $::C(fg) -width 2
  994. set xy {765 557 784 583}
  995. $w.c create rect $xy -fill $color -outline $::C(fg) -width 2
  996. Sine $w 658 580 765 580 3 15 -tag I15_s -fill $::C(fg) -width 3
  997. }
  998. proc Move15a {w} {
  999. set color $::C(15b)
  1000. $w.c scale I15a 824 599 1 .3 ;# Button down
  1001. set xy {765 621 681 621}
  1002. $w.c create line $xy -dash "-" -width 3 -fill $color -tag I15
  1003. }
  1004. proc Move15 {w {step {}}} {
  1005. set step [GetStep 15 $step]
  1006. set numsteps 6
  1007. if {$step == $numsteps+2} {
  1008. MoveAbs $w I15_star {-100 -100}
  1009. return 2
  1010. }
  1011. if {$step == 0} { ;# Break the light beam
  1012. Sparkle $w {-100 -100} I15_star
  1013. set xy {765 621 745 621}
  1014. $w.c coords I15 $xy
  1015. return 1
  1016. }
  1017. lassign [Anchor $w I15_s w] x0 y0
  1018. lassign [Anchor $w I15_s e] x1 y1
  1019. set x [expr {$x0 + ($x1-$x0) * ($step - 1) / double($numsteps)}]
  1020. MoveAbs $w I15_star [list $x $y0]
  1021. return 1
  1022. }
  1023. # Bell
  1024. proc Draw16 {w} {
  1025. set color $::C(16)
  1026. set xy {722 485 791 556}
  1027. $w.c create rect $xy -fill {} -outline $::C(fg) -width 3
  1028. set xy [box 752 515 25] ;# Bell
  1029. $w.c create oval $xy -fill $color -outline black -tag I16b -width 2
  1030. set xy [box 752 515 5] ;# Bell button
  1031. $w.c create oval $xy -fill black -outline black -tag I16b
  1032. set xy {784 523 764 549} ;# Clapper
  1033. $w.c create line $xy -width 3 -tag I16c -fill $::C(fg)
  1034. set xy [box 784 523 4]
  1035. $w.c create oval $xy -fill $::C(fg) -outline $::C(fg) -tag I16d
  1036. }
  1037. proc Move16 {w {step {}}} {
  1038. set step [GetStep 16 $step]
  1039. # Note: we never stop
  1040. lassign {760 553} Ox Oy
  1041. if {$step & 1} {
  1042. set beta 12
  1043. $w.c move I16b 3 0
  1044. } else {
  1045. set beta -12
  1046. $w.c move I16b -3 0
  1047. }
  1048. RotateItem $w I16c $Ox $Oy $beta
  1049. RotateItem $w I16d $Ox $Oy $beta
  1050. return [expr {$step == 1 ? 3 : 1}]
  1051. }
  1052. # Cat
  1053. proc Draw17 {w} {
  1054. set color $::C(17)
  1055. set xy {584 556 722 556}
  1056. $w.c create line $xy -fill $::C(fg) -width 3
  1057. set xy {584 485 722 485}
  1058. $w.c create line $xy -fill $::C(fg) -width 3
  1059. set xy {664 523 717 549} ;# Body
  1060. $w.c create arc $xy -outline $::C(fg) -fill $color -width 3 \
  1061. -style chord -start 128 -extent -260 -tag I17
  1062. set xy {709 554 690 543} ;# Paw
  1063. $w.c create oval $xy -outline $::C(fg) -fill $color -width 3 -tag I17
  1064. set xy {657 544 676 555}
  1065. $w.c create oval $xy -outline $::C(fg) -fill $color -width 3 -tag I17
  1066. set xy [box 660 535 15] ;# Lower face
  1067. $w.c create arc $xy -outline $::C(fg) -width 3 -style arc \
  1068. -start 150 -extent 240 -tag I17_
  1069. $w.c create arc $xy -outline {} -fill $color -width 1 -style chord \
  1070. -start 150 -extent 240 -tag I17_
  1071. set xy {674 529 670 513 662 521 658 521 650 513 647 529} ;# Ears
  1072. $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
  1073. $w.c create poly $xy -fill $color -outline {} -width 1 -tag {I17_ I17_c}
  1074. set xy {652 542 628 539} ;# Whiskers
  1075. $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
  1076. set xy {652 543 632 545}
  1077. $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
  1078. set xy {652 546 632 552}
  1079. $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
  1080. set xy {668 543 687 538}
  1081. $w.c create line $xy -fill $::C(fg) -width 3 -tag {I17_ I17w}
  1082. set xy {668 544 688 546}
  1083. $w.c create line $xy -fill $::C(fg) -width 3 -tag {I17_ I17w}
  1084. set xy {668 547 688 553}
  1085. $w.c create line $xy -fill $::C(fg) -width 3 -tag {I17_ I17w}
  1086. set xy {649 530 654 538 659 530} ;# Left eye
  1087. $w.c create line $xy -fill $::C(fg) -width 2 -smooth 1 -tag I17
  1088. set xy {671 530 666 538 661 530} ;# Right eye
  1089. $w.c create line $xy -fill $::C(fg) -width 2 -smooth 1 -tag I17
  1090. set xy {655 543 660 551 665 543} ;# Mouth
  1091. $w.c create line $xy -fill $::C(fg) -width 2 -smooth 1 -tag I17
  1092. }
  1093. proc Move17 {w {step {}}} {
  1094. set step [GetStep 17 $step]
  1095. if {$step == 0} {
  1096. $w.c delete I17 ;# Delete most of the cat
  1097. set xy {655 543 660 535 665 543} ;# Mouth
  1098. $w.c create line $xy -fill $::C(fg) -width 3 -smooth 1 -tag I17_
  1099. set xy [box 654 530 4] ;# Left eye
  1100. $w.c create oval $xy -outline $::C(fg) -width 3 -fill {} -tag I17_
  1101. set xy [box 666 530 4] ;# Right eye
  1102. $w.c create oval $xy -outline $::C(fg) -width 3 -fill {} -tag I17_
  1103. $w.c move I17_ 0 -20 ;# Move face up
  1104. set xy {652 528 652 554} ;# Front leg
  1105. $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
  1106. set xy {670 528 670 554} ;# 2nd front leg
  1107. $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
  1108. set xy {
  1109. 675 506 694 489 715 513 715 513 715 513 716 525 716 525 716 525
  1110. 706 530 695 530 679 535 668 527 668 527 668 527 675 522 676 517
  1111. 677 512
  1112. } ;# Body
  1113. $w.c create poly $xy -fill [$w.c itemcget I17_c -fill] \
  1114. -outline $::C(fg) -width 3 -smooth 1 -tag I17_
  1115. set xy {716 514 716 554} ;# Back leg
  1116. $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
  1117. set xy {694 532 694 554} ;# 2nd back leg
  1118. $w.c create line $xy -fill $::C(fg) -width 3 -tag I17_
  1119. set xy {715 514 718 506 719 495 716 488};# Tail
  1120. $w.c create line $xy -fill $::C(fg) -width 3 -smooth 1 -tag I17_
  1121. $w.c raise I17w ;# Make whiskers visible
  1122. $w.c move I17_ -5 0 ;# Move away from wall a bit
  1123. return 2
  1124. }
  1125. return 0
  1126. }
  1127. # Sling shot
  1128. proc Draw18 {w} {
  1129. set color $::C(18)
  1130. set xy {721 506 627 506} ;# Sling hold
  1131. $w.c create line $xy -width 4 -fill $::C(fg) -tag I18
  1132. set xy {607 500 628 513} ;# Sling rock
  1133. $w.c create oval $xy -fill $color -outline {} -tag I18a
  1134. set xy {526 513 606 507 494 502} ;# Sling band
  1135. $w.c create line $xy -fill $::C(fg) -width 4 -tag I18b
  1136. set xy { 485 490 510 540 510 575 510 540 535 491 } ;# Sling
  1137. $w.c create line $xy -fill $::C(fg) -width 6
  1138. }
  1139. proc Move18 {w {step {}}} {
  1140. set step [GetStep 18 $step]
  1141. set pos {
  1142. {587 506} {537 506} {466 506} {376 506} {266 506 x} {136 506}
  1143. {16 506} {-100 -100}
  1144. }
  1145. set b(0) {490 502 719 507 524 512} ;# Band collapsing
  1146. set b(1) {
  1147. 491 503 524 557 563 505 559 496 546 506 551 525 553 536 538 534
  1148. 532 519 529 499
  1149. }
  1150. set b(2) {491 503 508 563 542 533 551 526 561 539 549 550 530 500}
  1151. set b(3) {491 503 508 563 530 554 541 562 525 568 519 544 530 501}
  1152. if {$step >= [llength $pos]} {
  1153. return 0
  1154. }
  1155. if {$step == 0} {
  1156. $w.c delete I18
  1157. $w.c itemconfig I18b -smooth 1
  1158. }
  1159. if {[info exists b($step)]} {
  1160. $w.c coords I18b $b($step)
  1161. }
  1162. set where [lindex $pos $step]
  1163. MoveAbs $w I18a $where
  1164. if {[lindex $where 2] eq "x"} {
  1165. return 3
  1166. }
  1167. return 1
  1168. }
  1169. # Water pipe
  1170. proc Draw19 {w} {
  1171. set color $::C(19)
  1172. set xx {249 181 155 118 86 55 22 0}
  1173. foreach {x1 x2} $xx {
  1174. $w.c create rect $x1 453 $x2 467 -fill $color -outline {} -tag I19
  1175. $w.c create line $x1 453 $x2 453 -fill $::C(fg) -width 1;# Pipe top
  1176. $w.c create line $x1 467 $x2 467 -fill $::C(fg) -width 1;# Pipe bottom
  1177. }
  1178. $w.c raise I11i
  1179. set xy [box 168 460 16] ;# Bulge by the joint
  1180. $w.c create oval $xy -fill $color -outline {}
  1181. $w.c create arc $xy -outline $::C(fg) -width 1 -style arc \
  1182. -start 21 -extent 136
  1183. $w.c create arc $xy -outline $::C(fg) -width 1 -style arc \
  1184. -start -21 -extent -130
  1185. set xy {249 447 255 473} ;# First joint 26x6
  1186. $w.c create rect $xy -fill $color -outline $::C(fg) -width 1
  1187. set xy [box 257 433 34] ;# Bend up
  1188. $w.c create arc $xy -outline {} -fill $color -width 1 \
  1189. -style pie -start 0 -extent -91
  1190. $w.c create arc $xy -outline $::C(fg) -width 1 \
  1191. -style arc -start 0 -extent -90
  1192. set xy [box 257 433 20]
  1193. $w.c create arc $xy -outline {} -fill $::C(bg) -width 1 \
  1194. -style pie -start 0 -extent -92
  1195. $w.c create arc $xy -outline $::C(fg) -width 1 \
  1196. -style arc -start 0 -extent -90
  1197. set xy [box 257 421 34] ;# Bend left
  1198. $w.c create arc $xy -outline {} -fill $color -width 1 \
  1199. -style pie -start 1 -extent 91
  1200. $w.c create arc $xy -outline $::C(fg) -width 1 \
  1201. -style arc -start 0 -extent 90
  1202. set xy [box 257 421 20]
  1203. $w.c create arc $xy -outline {} -fill $::C(bg) -width 1 \
  1204. -style pie -start 0 -extent 90
  1205. $w.c create arc $xy -outline $::C(fg) -width 1 \
  1206. -style arc -start 0 -extent 90
  1207. set xy [box 243 421 34] ;# Bend down
  1208. $w.c create arc $xy -outline {} -fill $color -width 1 \
  1209. -style pie -start 90 -extent 90
  1210. $w.c create arc $xy -outline $::C(fg) -width 1 \
  1211. -style arc -start 90 -extent 90
  1212. set xy [box 243 421 20]
  1213. $w.c create arc $xy -outline {} -fill $::C(bg) -width 1 \
  1214. -style pie -start 90 -extent 90
  1215. $w.c create arc $xy -outline $::C(fg) -width 1 \
  1216. -style arc -start 90 -extent 90
  1217. set xy {270 427 296 433} ;# 2nd joint bottom
  1218. $w.c create rect $xy -fill $color -outline $::C(fg) -width 1
  1219. set xy {270 421 296 427} ;# 2nd joint top
  1220. $w.c create rect $xy -fill $color -outline $::C(fg) -width 1
  1221. set xy {249 382 255 408} ;# Third joint right
  1222. $w.c create rect $xy -fill $color -outline $::C(fg) -width 1
  1223. set xy {243 382 249 408} ;# Third joint left
  1224. $w.c create rect $xy -fill $color -outline $::C(fg) -width 1
  1225. set xy {203 420 229 426} ;# Last joint
  1226. $w.c create rect $xy -fill $color -outline $::C(fg) -width 1
  1227. set xy [box 168 460 6] ;# Handle joint
  1228. $w.c create oval $xy -fill $::C(fg) -outline {} -tag I19a
  1229. set xy {168 460 168 512} ;# Handle bar
  1230. $w.c create line $xy -fill $::C(fg) -width 5 -tag I19b
  1231. }
  1232. proc Move19 {w {step {}}} {
  1233. set step [GetStep 19 $step]
  1234. set angles {30 30 30}
  1235. if {$step == [llength $angles]} {
  1236. return 2
  1237. }
  1238. RotateItem $w I19b {*}[Centroid $w I19a] [lindex $angles $step]
  1239. return 1
  1240. }
  1241. # Water pouring
  1242. proc Draw20 {w} {
  1243. }
  1244. proc Move20 {w {step {}}} {
  1245. set step [GetStep 20 $step]
  1246. set pos {451 462 473 484 496 504 513 523 532}
  1247. set freq {20 40 40 40 40 40 40 40 40}
  1248. set pos {
  1249. {451 20} {462 40} {473 40} {484 40} {496 40} {504 40} {513 40}
  1250. {523 40} {532 40 x}
  1251. }
  1252. if {$step >= [llength $pos]} {
  1253. return 0
  1254. }
  1255. $w.c delete I20
  1256. set where [lindex $pos $step]
  1257. lassign $where y f
  1258. H2O $w $y $f
  1259. if {[lindex $where 2] eq "x"} {
  1260. return 3
  1261. }
  1262. return 1
  1263. }
  1264. proc H2O {w y f} {
  1265. set color $::C(20)
  1266. $w.c delete I20
  1267. Sine $w 208 428 208 $y 4 $f -tag {I20 I20s} -width 3 -fill $color \
  1268. -smooth 1
  1269. $w.c create line [$w.c coords I20s] -width 3 -fill $color -smooth 1 \
  1270. -tag {I20 I20a}
  1271. $w.c create line [$w.c coords I20s] -width 3 -fill $color -smooth 1 \
  1272. -tag {I20 I20b}
  1273. $w.c move I20a 8 0
  1274. $w.c move I20b 16 0
  1275. }
  1276. # Bucket
  1277. proc Draw21 {w} {
  1278. set color $::C(21)
  1279. set xy {217 451 244 490} ;# Right handle
  1280. $w.c create line $xy -fill $::C(fg) -width 2 -tag I21_a
  1281. set xy {201 467 182 490} ;# Left handle
  1282. $w.c create line $xy -fill $::C(fg) -width 2 -tag I21_a
  1283. set xy {245 490 237 535} ;# Right side
  1284. set xy2 {189 535 181 490} ;# Left side
  1285. $w.c create poly [concat $xy $xy2] -fill $color -outline {} \
  1286. -tag {I21 I21f}
  1287. $w.c create line $xy -fill $::C(fg) -width 2 -tag I21
  1288. $w.c create line $xy2 -fill $::C(fg) -width 2 -tag I21
  1289. set xy {182 486 244 498} ;# Top
  1290. $w.c create oval $xy -fill $color -outline {} -width 2 -tag {I21 I21f}
  1291. $w.c create oval $xy -fill {} -outline $::C(fg) -width 2 -tag {I21 I21t}
  1292. set xy {189 532 237 540} ;# Bottom
  1293. $w.c create oval $xy -fill $color -outline $::C(fg) -width 2 \
  1294. -tag {I21 I21b}
  1295. }
  1296. proc Move21 {w {step {}}} {
  1297. set step [GetStep 21 $step]
  1298. set numsteps 30
  1299. if {$step >= $numsteps} {
  1300. return 0
  1301. }
  1302. lassign [$w.c coords I21b] x1 y1 x2 y2
  1303. #lassign [$w.c coords I21t] X1 Y1 X2 Y2
  1304. lassign {183 492 243 504} X1 Y1 X2 Y2
  1305. set f [expr {$step / double($numsteps)}]
  1306. set y2 [expr {$y2 - 3}]
  1307. set xx1 [expr {$x1 + ($X1 - $x1) * $f}]
  1308. set yy1 [expr {$y1 + ($Y1 - $y1) * $f}]
  1309. set xx2 [expr {$x2 + ($X2 - $x2) * $f}]
  1310. set yy2 [expr {$y2 + ($Y2 - $y2) * $f}]
  1311. #H2O $w $yy1 40
  1312. $w.c itemconfig I21b -fill $::C(20)
  1313. $w.c delete I21w
  1314. $w.c create poly $x2 $y2 $x1 $y1 $xx1 $yy1 $xx2 $yy1 -tag {I21 I21w} \
  1315. -outline {} -fill $::C(20)
  1316. $w.c lower I21w I21
  1317. $w.c raise I21b
  1318. $w.c lower I21f
  1319. return [expr {$step == $numsteps-1 ? 3 : 1}]
  1320. }
  1321. # Bucket drop
  1322. proc Draw22 {w} {
  1323. }
  1324. proc Move22 {w {step {}}} {
  1325. set step [GetStep 22 $step]
  1326. set pos {{213 513} {213 523} {213 543 x} {213 583} {213 593}}
  1327. if {$step == 0} {$w.c itemconfig I21f -fill $::C(22)}
  1328. if {$step >= [llength $pos]} {
  1329. return 0
  1330. }
  1331. set where [lindex $pos $step]
  1332. MoveAbs $w I21 $where
  1333. H2O $w [lindex $where 1] 40
  1334. $w.c delete I21_a ;# Delete handles
  1335. if {[lindex $where 2] eq "x"} {
  1336. return 3
  1337. }
  1338. return 1
  1339. }
  1340. # Blow dart
  1341. proc Draw23 {w} {
  1342. set color $::C(23a)
  1343. set color2 $::C(23b)
  1344. set color3 $::C(23c)
  1345. set xy {185 623 253 650} ;# Block
  1346. $w.c create rect $xy -fill black -outline $::C(fg) -width 2 -tag I23a
  1347. set xy {187 592 241 623} ;# Balloon
  1348. $w.c create oval $xy -outline {} -fill $color -tag I23b
  1349. $w.c create arc $xy -outline $::C(fg) -width 3 -tag I23b \
  1350. -style arc -start 12 -extent 336
  1351. set xy {239 604 258 589 258 625 239 610} ;# Balloon nozzle
  1352. $w.c create poly $xy -outline {} -fill $color -tag I23b
  1353. $w.c create line $xy -fill $::C(fg) -width 3 -tag I23b
  1354. set xy {285 611 250 603} ;# Dart body
  1355. $w.c create oval $xy -fill $color2 -outline $::C(fg) -width 3 -tag I23d
  1356. set xy {249 596 249 618 264 607 249 596} ;# Dart tail
  1357. $w.c create poly $xy -fill $color3 -outline $::C(fg) -width 3 -tag I23d
  1358. set xy {249 607 268 607} ;# Dart detail
  1359. $w.c create line $xy -fill $::C(fg) -width 3 -tag I23d
  1360. set xy {285 607 305 607} ;# Dart needle
  1361. $w.c create line $xy -fill $::C(fg) -width 3 -tag I23d
  1362. }
  1363. proc Move23 {w {step {}}} {
  1364. set step [GetStep 23 $step]
  1365. set pos {
  1366. {277 607} {287 607} {307 607 x} {347 607} {407 607} {487 607}
  1367. {587 607} {687 607} {787 607} {-100 -100}
  1368. }
  1369. if {$step >= [llength $pos]} {
  1370. return 0
  1371. }
  1372. if {$step <= 1} {
  1373. $w.c scale I23b {*}[Anchor $w I23a n] .9 .5
  1374. }
  1375. set where [lindex $pos $step]
  1376. MoveAbs $w I23d $where
  1377. if {[lindex $where 2] eq "x"} {
  1378. return 3
  1379. }
  1380. return 1
  1381. }
  1382. # Balloon
  1383. proc Draw24 {w} {
  1384. set color $::C(24a)
  1385. set xy {366 518 462 665} ;# Balloon
  1386. $w.c create oval $xy -fill $color -outline $::C(fg) -width 3 -tag I24
  1387. set xy {414 666 414 729} ;# String
  1388. $w.c create line $xy -fill $::C(fg) -width 3 -tag I24
  1389. set xy {410 666 404 673 422 673 418 666} ;# Nozzle
  1390. $w.c create poly $xy -fill $color -outline $::C(fg) -width 3 -tag I24
  1391. set xy {387 567 390 549 404 542} ;# Reflections
  1392. $w.c create line $xy -fill $::C(fg) -smooth 1 -width 2 -tag I24
  1393. set xy {395 568 399 554 413 547}
  1394. $w.c create line $xy -fill $::C(fg) -smooth 1 -width 2 -tag I24
  1395. set xy {403 570 396 555 381 553}
  1396. $w.c create line $xy -fill $::C(fg) -smooth 1 -width 2 -tag I24
  1397. set xy {408 564 402 547 386 545}
  1398. $w.c create line $xy -fill $::C(fg) -smooth 1 -width 2 -tag I24
  1399. }
  1400. proc Move24 {w {step {}}} {
  1401. global S
  1402. set step [GetStep 24 $step]
  1403. if {$step > 4} {
  1404. return 0
  1405. } elseif {$step == 4} {
  1406. return 2
  1407. }
  1408. if {$step == 0} {
  1409. $w.c delete I24 ;# Exploding balloon
  1410. set xy {
  1411. 347 465 361 557 271 503 272 503 342 574 259 594 259 593 362 626
  1412. 320 737 320 740 398 691 436 738 436 739 476 679 528 701 527 702
  1413. 494 627 548 613 548 613 480 574 577 473 577 473 474 538 445 508
  1414. 431 441 431 440 400 502 347 465 347 465
  1415. }
  1416. $w.c create poly $xy -tag I24 -fill $::C(24b) -outline $::C(24a) \
  1417. -width 10 -smooth 1
  1418. set msg [subst $S(message)]
  1419. $w.c create text [Centroid $w I24] -text $msg -tag {I24 I24t} \
  1420. -justify center -font {{Times Roman} 18 bold}
  1421. return 1
  1422. }
  1423. $w.c itemconfig I24t -font [list {Times Roman} [expr {18 + 6*$step}] bold]
  1424. $w.c move I24 0 -60
  1425. $w.c scale I24 {*}[Centroid $w I24] 1.25 1.25
  1426. return 1
  1427. }
  1428. # Displaying the message
  1429. proc Move25 {w {step {}}} {
  1430. global S
  1431. set step [GetStep 25 $step]
  1432. if {$step == 0} {
  1433. set ::XY(25) [clock clicks -milliseconds]
  1434. return 1
  1435. }
  1436. set elapsed [expr {[clock clicks -milliseconds] - $::XY(25)}]
  1437. if {$elapsed < 5000} {
  1438. return 1
  1439. }
  1440. return 2
  1441. }
  1442. # Collapsing balloon
  1443. proc Move26 {w {step {}}} {
  1444. global S
  1445. set step [GetStep 26 $step]
  1446. if {$step >= 3} {
  1447. $w.c delete I24 I26
  1448. $w.c create text 430 755 -anchor s -tag I26 \
  1449. -text "click to continue" -font {{Times Roman} 24 bold}
  1450. bind $w.c <Button-1> [list Reset $w]
  1451. return 4
  1452. }
  1453. $w.c scale I24 {*}[Centroid $w I24] .8 .8
  1454. $w.c move I24 0 60
  1455. $w.c itemconfig I24t -font [list {Times Roman} [expr {30 - 6*$step}] bold]
  1456. return 1
  1457. }
  1458. ################################################################
  1459. #
  1460. # Helper functions
  1461. #
  1462. proc box {x y r} {
  1463. return [list [expr {$x-$r}] [expr {$y-$r}] [expr {$x+$r}] [expr {$y+$r}]]
  1464. }
  1465. proc MoveAbs {w item xy} {
  1466. lassign $xy x y
  1467. lassign [Centroid $w $item] Ox Oy
  1468. set dx [expr {$x - $Ox}]
  1469. set dy [expr {$y - $Oy}]
  1470. $w.c move $item $dx $dy
  1471. }
  1472. proc RotateItem {w item Ox Oy beta} {
  1473. set xy [$w.c coords $item]
  1474. set xy2 {}
  1475. foreach {x y} $xy {
  1476. lappend xy2 {*}[RotateC $x $y $Ox $Oy $beta]
  1477. }
  1478. $w.c coords $item $xy2
  1479. }
  1480. proc RotateC {x y Ox Oy beta} {
  1481. # rotates vector (Ox,Oy)->(x,y) by beta degrees clockwise
  1482. set x [expr {$x - $Ox}] ;# Shift to origin
  1483. set y [expr {$y - $Oy}]
  1484. set beta [expr {$beta * atan(1) * 4 / 180.0}] ;# Radians
  1485. set xx [expr {$x * cos($beta) - $y * sin($beta)}] ;# Rotate
  1486. set yy [expr {$x * sin($beta) + $y * cos($beta)}]
  1487. set xx [expr {$xx + $Ox}] ;# Shift back
  1488. set yy [expr {$yy + $Oy}]
  1489. return [list $xx $yy]
  1490. }
  1491. proc Reset {w} {
  1492. global S
  1493. DrawAll $w
  1494. bind $w.c <Button-1> {}
  1495. set S(mode) $::MSTART
  1496. set S(active) 0
  1497. }
  1498. # Each Move## keeps its state info in STEP, this retrieves and increments it
  1499. proc GetStep {who step} {
  1500. global STEP
  1501. if {$step ne ""} {
  1502. set STEP($who) $step
  1503. } elseif {![info exists STEP($who)] || $STEP($who) eq ""} {
  1504. set STEP($who) 0
  1505. } else {
  1506. incr STEP($who)
  1507. }
  1508. return $STEP($who)
  1509. }
  1510. proc ResetStep {} {
  1511. global STEP
  1512. set ::S(cnt) 0
  1513. foreach a [array names STEP] {
  1514. set STEP($a) ""
  1515. }
  1516. }
  1517. proc Sine {w x0 y0 x1 y1 amp freq args} {
  1518. set PI [expr {4 * atan(1)}]
  1519. set step 2
  1520. set xy {}
  1521. if {$y0 == $y1} { ;# Horizontal
  1522. for {set x $x0} {$x <= $x1} {incr x $step} {
  1523. set beta [expr {($x - $x0) * 2 * $PI / $freq}]
  1524. set y [expr {$y0 + $amp * sin($beta)}]
  1525. lappend xy $x $y
  1526. }
  1527. } else {
  1528. for {set y $y0} {$y <= $y1} {incr y $step} {
  1529. set beta [expr {($y - $y0) * 2 * $PI / $freq}]
  1530. set x [expr {$x0 + $amp * sin($beta)}]
  1531. lappend xy $x $y
  1532. }
  1533. }
  1534. return [$w.c create line $xy {*}$args]
  1535. }
  1536. proc RoundRect {w xy radius args} {
  1537. lassign $xy x0 y0 x3 y3
  1538. set r [winfo pixels $w.c $radius]
  1539. set d [expr {2 * $r}]
  1540. # Make sure that the radius of the curve is less than 3/8 size of the box!
  1541. set maxr 0.75
  1542. if {$d > $maxr * ($x3 - $x0)} {
  1543. set d [expr {$maxr * ($x3 - $x0)}]
  1544. }
  1545. if {$d > $maxr * ($y3 - $y0)} {
  1546. set d [expr {$maxr * ($y3 - $y0)}]
  1547. }
  1548. set x1 [expr { $x0 + $d }]
  1549. set x2 [expr { $x3 - $d }]
  1550. set y1 [expr { $y0 + $d }]
  1551. set y2 [expr { $y3 - $d }]
  1552. set xy [list $x0 $y0 $x1 $y0 $x2 $y0 $x3 $y0 $x3 $y1 $x3 $y2]
  1553. lappend xy $x3 $y3 $x2 $y3 $x1 $y3 $x0 $y3 $x0 $y2 $x0 $y1
  1554. return $xy
  1555. }
  1556. proc RoundPoly {canv xy radii args} {
  1557. set lenXY [llength $xy]
  1558. set lenR [llength $radii]
  1559. if {$lenXY != 2*$lenR} {
  1560. error "wrong number of vertices and radii"
  1561. }
  1562. set knots {}
  1563. lassign [lrange $xy end-1 end] x0 y0
  1564. lassign $xy x1 y1
  1565. lappend xy {*}[lrange $xy 0 1]
  1566. for {set i 0} {$i < $lenXY} {incr i 2} {
  1567. set radius [lindex $radii [expr {$i/2}]]
  1568. set r [winfo pixels $canv $radius]
  1569. lassign [lrange $xy [expr {$i + 2}] [expr {$i + 3}]] x2 y2
  1570. set z [_RoundPoly2 $x0 $y0 $x1 $y1 $x2 $y2 $r]
  1571. lappend knots {*}$z
  1572. lassign [list $x1 $y1] x0 y0
  1573. lassign [list $x2 $y2] x1 y1
  1574. }
  1575. set n [$canv create polygon $knots -smooth 1 {*}$args]
  1576. return $n
  1577. }
  1578. proc _RoundPoly2 {x0 y0 x1 y1 x2 y2 radius} {
  1579. set d [expr {2 * $radius}]
  1580. set maxr 0.75
  1581. set v1x [expr {$x0 - $x1}]
  1582. set v1y [expr {$y0 - $y1}]
  1583. set v2x [expr {$x2 - $x1}]
  1584. set v2y [expr {$y2 - $y1}]
  1585. set vlen1 [expr {sqrt($v1x*$v1x + $v1y*$v1y)}]
  1586. set vlen2 [expr {sqrt($v2x*$v2x + $v2y*$v2y)}]
  1587. if {$d > $maxr * $vlen1} {
  1588. set d [expr {$maxr * $vlen1}]
  1589. }
  1590. if {$d > $maxr * $vlen2} {
  1591. set d [expr {$maxr * $vlen2}]
  1592. }
  1593. lappend xy [expr {$x1 + $d * $v1x/$vlen1}] [expr {$y1 + $d * $v1y/$vlen1}]
  1594. lappend xy $x1 $y1
  1595. lappend xy [expr {$x1 + $d * $v2x/$vlen2}] [expr {$y1 + $d * $v2y/$vlen2}]
  1596. return $xy
  1597. }
  1598. proc Sparkle {w Oxy tag} {
  1599. set xy {299 283 298 302 295 314 271 331 239 310 242 292 256 274 281 273}
  1600. foreach {x y} $xy {
  1601. $w.c create line 271 304 $x $y -fill white -width 3 -tag $tag
  1602. }
  1603. MoveAbs $w $tag $Oxy
  1604. }
  1605. proc Centroid {w item} {
  1606. return [Anchor $w $item c]
  1607. }
  1608. proc Anchor {w item where} {
  1609. lassign [$w.c bbox $item] x1 y1 x2 y2
  1610. if {[string match *n* $where]} {
  1611. set y $y1
  1612. } elseif {[string match *s* $where]} {
  1613. set y $y2
  1614. } else {
  1615. set y [expr {($y1 + $y2) / 2.0}]
  1616. }
  1617. if {[string match *w* $where]} {
  1618. set x $x1
  1619. } elseif {[string match *e* $where]} {
  1620. set x $x2
  1621. } else {
  1622. set x [expr {($x1 + $x2) / 2.0}]
  1623. }
  1624. return [list $x $y]
  1625. }
  1626. DoDisplay $w
  1627. Reset $w
  1628. Go $w ;# Start everything going