- latitude, longitude
- altitude (ft over sea level)
- heading (compass direction where nose points)
- horizontal angle (0 for level flight, positive for nose up)
- vertical angle (0 if both wings are at same height, positive if left is lower)
- horizontal speed (mph, over ground)
- vertical speed (1000 ft/min, positive for ascending)
- gas throttle, which influences speed and fuel consumption
- <Up> lowers nose
- <Down> raises nose
- <Left>, <Right> lower the corresponding wing
package require Tk proc main {} { wm geometry . +0+0 pack [canvas .c -bg lightblue] set ::g(canvas) .c .c create window 15 10 -window [button .r -text Reset -command reset] .c create window 230 10 -window [button .x -text X -command exit] .c create poly 0 100 240 100 240 200 0 200 -fill green -tag ground .c create line 110 100 130 100 .c create line 120 95 120 105 .c create line 0 190 2 190 -fill blue -tags multi -arrow last .c create text 225 175 -tag cname .c create line 225 185 225 195 -arrow first -arrowshape {3 5 3} -tag compass .c create rect 0 200 240 300 -fill grey -tag dashboard .c create rect 15 205 25 215 -fill yellow -outline yellow -tag hilite foreach i {0 1 2 3 4 5 6 7 8 9} { .c create text [expr $i*20+20] 210 -text $i -tag gas$i .c bind gas$i <1> "set g(gas) $i" } trace var ::g(gas) w {.c coords hilite [.c bbox gas$::g(gas)] ;#} set x 10; set y 230 foreach i {lat lon alt head hor ver fuel spd vspd} { .c create text $x $y -text $i -anchor w incr x 50 ctextvar .c $x $y g($i) if {[incr x 20]>180} {set x 10 ; incr y 13} } bind . <Up> {incr g(hor) -1} bind . <Down> {incr g(hor) 1} bind . <Left> {incr g(ver) -1} bind . <Right> {incr g(ver) 1} reset } #-- canvas text variable, auto-update proc ctextvar {w x y var} { $w create text $x $y -tag var$var trace var ::$var w "$w itemconfig var$var -text \$::$var ;#" } proc reset {} { foreach event [after info] {after cancel $event} array set ::g { lat 0 lon 0 alt 0 head 0 hor 0 ver 0 gas 0 spd 0 vspd 0 fuel 5000 } every 250 {recompute; redraw $::g(canvas)} }if 0 {The behavior of the plane is modelled by recomputing parameters from other parameters - please improve if you know better! Some important points:
- If in flight speed drops below 50 mph, the plane "stalls": the nose dips deep down. PULL UP!
- If speed exceeds 250 mph, the motor turns off
- If no fuel is left, the motor turns off too (obviously). You may still glide down.
proc recompute {} { global g if {$g(gas)>4||$g(alt)} { set g(spd) [expr {round($g(spd)+$g(gas)-4-$g(hor)*.5 - abs($g(ver))*.1)}] } if {$g(alt)>0 && $g(spd)<50} { tk_messageBox -message STALL set g(hor) -30 } set g(fuel) [expr {$g(fuel)-$g(gas)/2}] if {$g(fuel)<=0} {set g(fuel) 0; set g(gas) 0} if {$g(spd)>250} {set g(gas) 0} set g(vspd) $g(hor) incr g(alt) $g(vspd) if {$g(alt)<1 && $g(vspd)} land set g(head) [format %.1f [expr {fmod($g(head)+$g(ver)*.1+360,360)}]] set a [expr {($g(head)-90)*acos(-1)/180}] set g(lat) [format %.3f [expr {$g(lat)+cos($a)*$g(spd)*.0001}]] set g(lon) [format %.3f [expr {$g(lon)+sin($a)*$g(spd)*.00005}]] } proc land {} { global g foreach event [after info] {after cancel $event} if {$g(vspd)>-2} { set t "Smooth landing - congrats!" } elseif {$g(vspd)>-8} { set t "Rough landing - plane may need repair" } else { set t "CRASH!!!\nRelatives will be notified" crash } set dist [expr {hypot($g(lat),$g(lon))*10}] append t "\n[format %.1f $dist] miles off target" tk_messageBox -message $t reset } proc crash {} { set c $::g(canvas) $c config -bg red $c itemconfig ground -fill red } proc redraw w { global g set y [expr {100+$g(hor)*3}] set y1 [expr {$y+$g(ver)*3}] set y2 [expr {$y-$g(ver)*3}] $w coords ground 0 $y1 240 $y2 240 200 0 200 if {$g(alt)<500} { $w config -bg lightblue $w itemconfig ground -fill green } elseif {$g(alt)<550} { $w config -bg white $w itemconfig ground -fill white } else { $w config -bg lightblue $w itemconfig ground -fill white } set x1 [expr {5+$g(spd)/2}] set y0 [expr {195-$g(alt)/10}] set y1 [expr {$y0-$g(vspd)*2}] $w coords multi 0 $y0 $x1 $y1 set a [expr {($g(head)+90)*acos(-1)/180.}] set x [expr {cos($a)*6}] set y [expr {sin($a)*6}] $w coords compass [expr {225-$x}] [expr {190-$y}] [expr {225+$x}] [expr {190+$y}] $w itemconfig multi -fill [expr {$g(spd)>60 && $g(spd)<230? "blue": "red"}] $w itemconfig cname -text [compass'name $g(head)] } proc compass'name hdg { lindex {N NNE NE ENE E ESE SE SSE S SSW SW WSW W WNW NW NNW N} [expr {round($hdg/360.*16.)}] } proc every {ms body} {eval $body; after $ms [info level 0]} main
if 0 {Finally, some hints for a successful flight, starting from take-off:
- Full throttle (9)
- When speed is above 50, you can pull up
- Adjust ascent so speed remains constant
- When you reach desired height, pull down until vspd=0
- For level flight at constant speed, set throttle to 4
- For landing, throttle to 0
- Adjust descent so speed remains constant
- Close to ground reduce descent so you finally land with vspd=-1
- If speed falls close to 50 mph, increase throttle to avoid stall (which is fatal if close to ground)
PocketPC | Arts and crafts of Tcl-Tk programming Category Games