Tcl HomeTcl Home hosted by
ActiveState

Google SiteSearch

Cross Eyed?

Here's another Tcl application that demonstrates Tcl's interactive feedback. Move the mouse around inside the square and watch those eyes follow your mouse cursor. Then give those eyes a rest when you move the mouse out of the square.

P.S. Yes, those eyes really do blink!

Source

set cx 400
set cy 400
set r 15
if {[info exists embed_args(width)]} { set cx $embed_args(width) }
if {[info exists embed_args(height)]} { set cy $embed_args(height) }
if {[info exists embed_args(radius)]} { set r $embed_args(radius) }

if {![info exists embed_args(eyeColor)]} { set embed_args(eyeColor) black }

canvas .c -width $cx -height $cy -bg white
pack .c
set eye1(x) [expr $cx/2-4*$r]
set eye1(y) [expr $cy/2]
set eye2(x) [expr $cx/2+4*$r]
set eye2(y) [expr $cy/2]
proc makeeye {x y} {
    global r embed_args
    set b [.c create oval [expr $x-3*$r] [expr $y-4*$r] [expr $x+3*$r] \
	[expr $y+4*$r] -width 3 -fill white -outline black]
    set a [.c create oval [expr $x-$r] [expr $y-$r] [expr $x+$r] [expr $y+$r] \
	-fill $embed_args(eyeColor) -outline {}]
    .c bind $a <Enter> ".c itemconfig $a -fill red"
    .c bind $a <Leave> ".c itemconfig $a -fill $embed_args(eyeColor)"
    return [list $a $b]
}
proc moveeye {eyename x y} {
    global r embed_args
    upvar #0 $eyename eye
    set x [expr $x-$eye(x)]
    set y [expr $y-$eye(y)]
    set l [expr sqrt($x*$x+$y*$y)]
    if $l<$r {
	set cx $x
	set cy $y
    } else {
	set cx [expr $r*$x/$l]
	set cy [expr $r*$y/$l]
    }
    .c coords $eye(id) [expr $cx-$r+$eye(x)] [expr $cy-$r+$eye(y)] \
	[expr $cx+$r+$eye(x)] [expr $cy+$r+$eye(y)]
}
proc blink {} {
    global eyesOpen bigEye blinklist blinklength blinkindex eye1 eye2
    if {$eyesOpen == 1} {
	set eyesOpen 0
	.c itemconfigure $bigEye(0) -fill black
	.c itemconfigure $bigEye(1) -fill black
	.c lower $eye1(id)
	.c lower $eye2(id)
	after 200 blink
    } else {
	set delay [lindex $blinklist $blinkindex]
	incr blinkindex
	if {$blinkindex >= $blinklength} {
	    set blinkindex 0
	}
	set eyesOpen 1
	.c itemconfigure $bigEye(0) -fill white
	.c itemconfigure $bigEye(1) -fill white
	.c raise $eye1(id)
	.c raise $eye2(id)
	after $delay blink
    }
}
set blinklist {
    500 5000 2000 3000 10000 2000 3000 2000 500 200 3000 500 1000
    2000 300 300 2000 8000 2000 400 400 2000
}
set blinklength [llength $blinklist]
set blinkindex 0
set eyesOpen 1
set eye [makeeye $eye1(x) $eye1(y)]
set eye1(id) [lindex $eye 0]
set bigEye(0) [lindex $eye 1]
set eye [makeeye $eye2(x) $eye2(y)]
set eye2(id) [lindex $eye 0]
set bigEye(1) [lindex $eye 1]
bind all <Motion> "moveeye eye1 %x %y; moveeye eye2 %x %y"
after 1000 blink