FF - 2008-01-17 - I'm just playing with speed and acceleration.... I also added a collision check at bounds. I wanted to add multiple objects and collision check between every object, but I figured it would have been a pain...
In the beginning I was working with vectors in polar coordinates, but I figured that also was a pain, so I switched to rect coords, but here and there there in the code could be some wastes of polar stuff :-)
set PI [expr atan(1)*4] set x 50.0 ; set y 50.0 set vec_x 0.0 ; set vec_y 0.0 set timediv 50.0 array set input { joy_sz 64 target null dragging 0 dx 0.0 dy 0.0 } set cnv [canvas .c -width 640 -height 400 -background white] set joy [canvas .j -width $::input(joy_sz) -height $::input(joy_sz) -background gray] grid $cnv -column 0 -row 0 -columnspan 2 -sticky news grid columnconfigure . 0 -weight 10 grid rowconfigure . 0 -weight 10 grid [label .l1 -textvar ::lab1] -column 0 -row 1 grid [checkbutton .cb1 -text Spring -variable ::spring] -column 0 -row 2 grid [checkbutton .cb2 -text Control_accel -variable ::mode] -column 0 -row 3 grid $joy -column 1 -row 1 -rowspan 3 -sticky news proc init_vect {cnv {bdot 1}} { if $bdot { $cnv create rectangle 0 0 10 10 -tags {dot} -fill blue } else { $cnv create line [expr $::input(joy_sz)*0.5] 0 [expr $::input(joy_sz)*0.5] $::input(joy_sz) $cnv create line 0 [expr $::input(joy_sz)*0.5] $::input(joy_sz) [expr $::input(joy_sz)*0.5] } $cnv create line 0 0 10 10 -tags {vector vector_line} -fill red $cnv create polygon 0 0 10 10 20 20 -tags {vector vector_arrow} -fill red } proc rec2pol {dx dy} { if {$dx == 0} {set angle [expr $::PI*(($dy>0)?0.5:1.5)]} \ {set angle [expr fmod($::PI*(($dx>=0)?2:3)+atan(+1.0*$dy/$dx), $::PI*2)]} set length [expr sqrt(pow($dx,2)+pow($dy,2))] return [list $angle $length] } proc upd_vect_pol {cnv x y lx ly} { $cnv coords dot [expr $x-5] [expr $y-5] [expr $x+5] [expr $y+5] set ex [expr $x+$lx] ; set ey [expr $y+$ly] $cnv coords vector_line $x $y $ex $ey set angle [lindex [rec2pol $lx $ly] 0] set Al [expr fmod($::PI*1.25+$angle, $::PI*2)] set Ar [expr fmod($::PI*2.75+$angle, $::PI*2)] if {$lx != 0 || $ly != 0} { $cnv coords vector_arrow \ [expr $ex+cos($Al)*6] [expr $ey+sin($Al)*6] \ $ex $ey [expr $ex+cos($Ar)*6] [expr $ey+sin($Ar)*6] } else { $cnv coords vector_arrow \ [expr $x-3] $y $x [expr $y-3] [expr $x+3] $y $x [expr $y+3] } } proc upd {__cnv st {ex_ 0} {ey_ 0}} { if {$st == 0 && $::input(dragging)} { set ::input(dx) [expr $ex_-$::input(joy_sz)*0.5] set ::input(dy) [expr $ey_-$::input(joy_sz)*0.5] upd_vect_pol $::joy [expr $::input(joy_sz)*0.5] [expr $::input(joy_sz)*0.5] $::input(dx) $::input(dy) upd_vect_pol $::cnv $::x $::y $::vec_x $::vec_y } elseif {$st > 0} { set ::input(dragging) 1 } elseif {$st < 0} { set ::input(dragging) 0 if $::spring { set ::input(dx) 0 ; set ::input(dy) 0 ; upd_vect_pol $::joy [expr $::input(joy_sz)*0.5] [expr $::input(joy_sz)*0.5] $::input(dx) $::input(dy) } } } proc go {cnv} { set amt 0.1 # handle speed vector / acceleration if {$::mode == 0} { set ::vec_x $::input(dx) set ::vec_y $::input(dy) } elseif {$::mode == 1} { set ::vec_x [expr $::vec_x+$::input(dx)*$amt] set ::vec_y [expr $::vec_y+$::input(dy)*$amt] } set ::x [expr $::x+$::vec_x*$amt] set ::y [expr $::y+$::vec_y*$amt] # handle collisions set cnvw [expr ([winfo width $cnv]-[winfo reqwidth $cnv]+[$cnv cget -width])] set cnvh [expr ([winfo height $cnv]-[winfo reqheight $cnv]+[$cnv cget -height])] if {$::x < 0} { set ::x [expr 0-$::x] set ::vec_x [expr 0-$::vec_x] } elseif {$::x > $cnvw} { set ::x [expr $cnvw*2-$::x] set ::vec_x [expr 0-$::vec_x] } if {$::y < 0} { set ::y [expr 0-$::y] set ::vec_y [expr 0-$::vec_y] } elseif {$::y > $cnvh} { set ::y [expr $cnvh*2-$::y] set ::vec_y [expr 0-$::vec_y] } set ::lab1 "D(joy)=(${::input(dx)},${::input(dy)}) Vec=(${::vec_x},${::vec_y}) w=$cnvw h=$cnvh" upd_vect_pol $cnv $::x $::y $::vec_x $::vec_y after [expr int(1000/$::timediv)] [list go $cnv] } init_vect $cnv init_vect $joy 0 upd $joy 1; upd $joy 0 [expr $::input(joy_sz)*0.5] [expr $::input(joy_sz)*0.5]; upd $joy -1 bind $cnv <ButtonPress-1> {set ::x %x ; set ::y %y} bind $joy <ButtonPress-1> {upd %W 1} bind $joy <ButtonRelease-1> {upd %W -1} bind $joy <ButtonPress-3> {upd %W 1; upd %W 0 %x %y; upd %W -1} bind $joy <Motion> {upd %W 0 %x %y} go $cnv