- 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]}
mainif 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

