Description edit
Alex Caldwell M.D.:This is a project I started while trying to teach myself Tcl/Tk. It is a moving map using an aviation sectional chart. You can fly sailplanes over the map after selecting a set of goals, usually a triangular course. You can launch multiple sailplanes. Give each one a unique "contest ID". You must "stop flying" or pause in order to launch a new sailplane. You can control the sailplane who's ID is in the box with the arrow keys. Pause or "stop flying" to Change ID no. to control a different sailplane. The other ones will continue on the same course and speed as they were on. Left and Right arrow steer left and right. Down arrow speeds up the sailplane. Up arrow slows it down. Your sailplane starts with 5000 ft. of altitude. There is a polar performance curve similar to a real sailplane. So if you try to fly faster to get ahead, you will lose altitude faster and risk "landing out" or running out of altitude. You can regain lost altitude by slowing down and lingering in randomly generated thermals of varying strength that appear on the map as brown smoke stack like images. Flying faster does not make you win. The pilot that makes the best judgement of how fast or slow to fly, given the lift conditions, will win. In general, if the lift conditions are strong and lots of thermals can be reached, it will pay to fly fast and reach the next thermal quicker in spite of the more rapid altitude loss. If the lift conditions are weak, it will take much longer to regain lost altitude, so it will pay you to fly slower between thermals and conserve your altitude. If you run out of altitude, you "land out" and the game is over for you. There is one consolation not available in a real sailplane race. If you can maneuver your glider behind an opponent, and line up your course in his or her direction, pressing the space bar will launch a cruise missle in his or her direction. If it hits within the bounding box of the opponents glider, he or she will disintegrate and be removed from competition.Problems edit
- The distance calculations for this particular map are all hard coded in the program. Need to develop ability to import any map and calibrate flexibly, so the distances can be calculated on any chosen map.
- The code violates a lot of good Tcl coding practices, which I did not know when I started out, so it may be obfuscated.
Goals edit
- I have a preliminary network game version that connects to a server, so two clients can play each other from remote network computers, it works, but it has a few lingering problems.
- Use Tcl's new serial connection abilities to connect directly to a GPS receiver and plot courses in real time. Possibly on a PDA. The program is able now to read a Garmin .trk file and plot the positions on the map.
- Add ability to import an "IGC" file, a special GPS file format used by glider pilots. So you can replay a GPS recording of a real glider flight.
- Add circling flight by adding code such that when the speed goes below a certain value, the glider will start circling probably in a random right or left direction. Or when the steering input goes above a certain value, the glider will circle in that direction. Smaller imputs would continue to alter the straight line course.
- A 3-D version using Tkogl, the Tcl extension to OpenGL
- Hook it up to a joystick for speed and steering input.
RS: Thanks for showing this to us! Next question would be, whether it can be downloaded at some place?
You can download a Starkit from http://tcl.tk/starkits/soarmap2.kit
Here's the code. You also need these other two files saved in the same directory for the images:
- http://tkfp.sourceforge.net/soarmap/soarmap2.tcl - the program file
- http://tkfp.sourceforge.net/soarmap/largeclr.gif - the map image background - size 900kb
- http://tkfp.sourceforge.net/soarmap/pic45tra.gif - a small glider icon image
- http://tkfp.sourceforge.net/soarmap/test2.trk - a Garmin GPS track file to practice plotting fixes on map
Here's the network version where two or more players can connect to a server and play each other remotely. Requires Incr Tcl extension for Tcl/Tk. It basically works for the most part. Server based on some examples in "Incr Tcl/Tk from the Ground Up" by Chad Smith. Follow instructions in the README file.
The code for the non-network version.
# program for Tcl/Tk (free standing version - not for plug-in) # By Alex Caldwell M.D. # [email protected] # Jan 5, 1997 # Feb 11, 1999 # Feb 16, 1999 # Feb 21, 1999 # this section doesn't do anything functional. It was just a way to document the important # global variables in the program global i ;# variable that stores background image data for sectional map global g ;# variable that stores background image data for little gliders global bmp ;# variable that stores bitmap image global IC ;# used in great circle distance calculation global COURSE ;# compass course calculated from the course leg selected global HEADING ;# an array that holds the currently selected contestant's heading global TURNPOINT1 ;# variable that stores the name of turnpoint1 global TURNPOINT2 ;# variable that stores the name of turnpoint2 global turnpoints ;# list that stores the list of turnpoint names global latdegrees ;# list that stores a list of the turnpoint latitude degrees with the minutes truncated. global latmin global londegrees global lonmin global latdeg1 global latmin1 global londeg1 global lonmin1 global latdeg2 global latmin2 global londeg2 global lonmin2 global XAXIS ;# variable that stores the difference between the x coordinates of the two turnpoints. global YAXIS ;# variable that stores the difference between the y coordinates of the two turnpoints. global X1 ;# the x coordinate of the first turnpoint. global X2 ;# the x coordinate of the second turnpoint. global Y1 ;# the y coordinate of the first turnpoint. global Y2 ;# the y coordinate of teh second turnpoint. global SPEED ;# an array that stores the value of each contestant's current speed global ALTITUDE ;# an array that stores the value of each contestant's current altitude global text ;# an array that stores the value of each contestant's contest no. global ID ;# an array that stores the id of each contestant's small altitude text display global shadow ;# an array that stores the id of each contestant's shadow so it can be moved closer as altitude decreases global fileposition global filecounter global filelinenumber global fileid global glider ;# an array that stores the canvas id no.'s of the glider images. global contestno ;# a variable that stores the current contest no. global yfraction ;# I can't remember what this was supposed to do but I was afraid to delete it global xfraction ;# I can't remember what this was supposed to do but I was afraid to delete it global combatants ;# a list of the players by their contest no. global thermals ;# a list of the thermals by no. global thermalstrength ;# an array that stores the strength of each thermal global daystrength ;# a variable that sets the ramndom range for the average thermal strength global autoscroll ;# stores value of variable that controls whether the map scrolls along with the glider global tracking ;# variable that controls whether tracking is on or off global distanceflown ;# array storing the value of distance flown for each glider global angle_radians ;# variable used in the calcheading change proc to make glider circle # this initializes some important global variables set contestno IB set yfraction 0 set xfraction 0 set TURNPOINT1 "Avenal" set TURNPOINT2 "Delano" set SPEED(IB) 60 set ALTITUDE(IB) 5000 set HEADING(IB) 0 set fileposition 332 set filecounter 0 set filelinenumber 0 set daystrength 6 set autoscroll on set tracking on set angle_radians 0 set turnpoints {Avenal Corcoran Delano Porterville "New Cuyama"} set latdegrees {36 36 35 36 34} set latmin {0 6.15 44.74 1.78 57} set londegrees {120 119 119 119 119} set lonmin {8 35.69 14.19 3.76 42} proc RandomInit { seed } { global rando@mSeed set randomSeed $seed } proc Random {} { global randomSeed set randomSeed [expr ($randomSeed*9301 + 49297) % 233280] return [expr $randomSeed/double(233280)] } proc RandomRange { range } { expr int([Random]*$range) } RandomInit [pid] #**************************************************************************************** proc getturnpoint {} { global TURNPOINT1 global TURNPOINT2 global X1 X2 Y1 Y2 global contestno global SPEED global HEADING global daystrength frame .turnpointframe frame .turnpointframe.turnpointframe1 frame .turnpointframe.turnpointframe2 label .turnpointframe.turnpointframe1.label1 -text {Select Turnpoint 1} -relief groove label .turnpointframe.turnpointframe2.label2 -text {Select Turnpoint2 } -relief groove menubutton .turnpointframe.turnpointframe1.menu1 -text $TURNPOINT1 \ -menu .turnpointframe.turnpointframe1.menu1.sub1 -relief raised set men1 [menu .turnpointframe.turnpointframe1.menu1.sub1] $men1 add radio -label Avenal -variable TURNPOINT1 -value Avenal \ -command ".turnpointframe.turnpointframe1.menu1 configure -text Avenal" $men1 add r3adio -label Corcoran -variable TURNPOINT1 -value Corcoran \ -command ".turnpointframe.turnpointframe1.menu1 configure -text Corcoran" $men1 add radio -label Delano -variable TURNPOINT1 -value Delano \ -command ".turnpointframe.turnpointframe1.menu1 configure -text Delano" $men1 add radio -label Porterville -variable TURNPOINT1 -value Porterville \ -command ".turnpointframe.turnpointframe1.menu1 configure -text Porterville" $men1 add radio -label {New Cuyama} -variable TURNPOINT1 -value {New Cuyama} \ -command ".turnpointframe.turnpointframe1.menu1 configure -text {New Cuyama}" menubutton .turnpointframe.turnpointframe2.menu2 -text $TURNPOINT2 \ -menu .turnpointframe.turnpointframe2.menu2.sub1 -relief raised set men2 [menu .turnpointframe.turnpointframe2.menu2.sub1] $men2 add radio -label Avenal -variable TURNPOINT2 -value Avenal \ -command ".turnpointframe.turnpointframe2.menu2 configure -text Avenal" $men2 add radio -label Corcoran -variable TURNPOINT2 -value Corcoran \ -command ".turnpointframe.turnpointframe2.menu2 configure -text Corcoran" $men2 add radio -label Delano -variable TURNPOINT2 -value Delano \ -command ".turnpointframe.turnpointframe2.menu2 configure -text Delano" $men2 add radio -label Porterville -variable TURNPOINT2 -value Porterville \ -command ".turnpointframe.turnpointframe2.menu2 configure -text Porterville" $men2 add radio -label {New Cuyama} -variable TURNPOINT2 -value {New Cuyama} \ -command ".turnpointframe.turnpointframe2.menu2 configure -text {New Cuyama}" label .turnpointframe.turnpointframe1.contestnolabel -text {Enter Contest No.} label .turnpointframe.turnpointframe1.daystrength -text {Thermal Strength} entry .turnpointframe.turnpointframe2.contestnoentry -textvariable contestno -width 5 menubutton .turnpointframe.turnpointframe2.daystrength -text weak \ -menu .turnpointframe.turnpointframe2.daystrength.m -relief raised menu .turnpointframe.turnpointframe2.daystrength.m .turnpointframe.turnpointframe2.daystrength.m add radio -label weak -variable daystrength -value 6 .turnpointframe.turnpointframe2.daystrength.m add radio -label medium -variable daystrength -value 11 .turnpointframe.turnpointframe2.daystrength.m add radio -label strong -variable daystrength -value 18 button .turnpointframe.updatebutton -text "Start New Leg" -command {destroybuttons getcoord calcdist $latdeg1 $latmin1 $londeg1 $lonmin1 $latdeg2 $latmin2 $londeg2 $lonmin2 calcheading $latdeg1 $latmin1 $londeg1 $lonmin1 $latdeg2 $latmin2 $londeg2 $lonmin2 plotline $latdeg1 $latmin1 $londeg1 $lonmin1 $latdeg2 $latmin2 $londeg2 $lonmin2 showdist} button .turnpointframe.launchglider -text "Launch Glider" -command {launchGlider;destroybuttons;showdist} button .turnpointframe.flybutton -text {Start Flying} -command {displayInfo} scale .turnpointframe.speedscale -from 40 -to 200 -length 250 -variable SPEED($contestno) -orient horizontal \ -label "Speed $contestno - kts" -tickinterval 50 -showvalue true bind . <KeyPress-Down> {set SPEED($contestno) [expr $SPEED($contestno) - 1]} bind . <KeyPress-Up> {set SPEED($contestno) [expr $SPEED($contestno) + 1]} scale .turnpointframe.headingscale -from -75 -to 75 -length 250 -variable HEADING($contestno) -orient horizontal \ -label "Steer $contestno - L/R" -tickinterval 15 -showvalue true bind . <KeyPress-Left> {set HEADING($contestno) [expr $HEADING($contestno) -1]} bind . <KeyPress-Right> {set HEADING($contestno) [expr $HEADING($contestno) +1]} button .turnpointframe.gpsbutton1 -text {last GPS fix} -command {gpsdisplay1} button .turnpointframe.gpsbutton2 -text {plot all GPS fixes} -command {gpsdisplay2} pack .frame .turnpointframe -side left pack .turnpointframe.turnpointframe1 .turnpointframe.turnpointframe2 -side left pack .turnpointframe.turnpointframe1.label1 pack .turnpointframe.turnpointframe1.menu1 -padx 5 -pady 5 pack .turnpointframe.turnpointframe2.label2 pack .turnpointframe.turnpointframe2.menu2 -padx 5 -pady 5 pack .turnpointframe.turnpointframe1.contestnolabel pack .turnpointframe.turnpointframe1.daystrength pack .turnpointframe.turnpointframe2.contestnoentry pack .turnpointframe.turnpointframe2.daystrength pack .turnpointframe.updatebutton .turnpointframe.launchglider \ .turnpointframe.flybutton .turnpointframe.gpsbutton1 \ .turnpointframe.gpsbutton2 \ .turnpointfra3me6.speedscale .turnpointframe.headingscale } #********************************************************************************************* proc destroybuttons {} { foreach item [winfo children .frame] { destroy $item } } #********************************************************************************************* # this is for launching a new glider whenever the launch glider button is pressed. # it is always launched at the first turnpoint that is currently selected with 5000 ft of altitude. proc launchGlider { } { global XAXIS YAXIS COURSE ALTITUDE ID shadow contestno combatants X1 Y1 glider text set Y1 [expr $Y1 * 2136] set X1 [expr $X1 * 1759] # this creates the glider image # depending on the direction of flight, a different image is chosen. # this creates the glider image and the shadow image # this creates the shadow of the glider first so the glider will be over it in the object order if {$XAXIS < 0 } { if {$COURSE > 225 } { set shadow($contestno) [.c.canvas create image [expr $X1 + ($XAXIS/2)] [expr $Y1 + ($YAXIS/2)] \ -image glidershadowwest -anchor center -tags "st $contestno"] set glider($contestno) [.c.canvas create image $X1 $Y1 \ -image gliderpairwest -anchor center -tags "st $contestno"] } else { set shadow($contestno) [.c.canvas create image [expr $X1 + ($XAXIS/2)] [expr $Y1 + ($YAXIS/2)] \ -image glidershadowsouthwest -anchor center -tags "st $contestno"] set glider($contestno) [.c.canvas create image $X1 $Y1 \ -image gliderpairsouthwest -anchor center -tags "st $contestno"] } } else { if {$COURSE > 28 && $COURSE < 349} { set shadow($contestno) [.c.canvas create image [expr $X1 + ($XAXIS/2)] [expr $Y1 + ($YAXIS/2)] \ -image glidershadow -anchor center -tags "st $contestno" ] set glider($contestno) [.c.canvas create image $X1 $Y1 \ -image gliderpair -anchor center -tags "st $contestno"] } else { set shadow($contestno) [.c.canvas create image [expr $X1 + ($XAXIS/2)] [expr $Y1 + ($YAXIS/2)] \ -image glidershadownortheast -anchor center -tags "st $contestno" ] set glider($contestno) [.c.canvas create image $X1 $Y1 \ -image gliderpairnortheast -anchor center -tags "st $contestno"] } } # place the contest no near the glider and move it along with it. set text($contestno) [.c.canvas create text [expr $X1 + 22] [expr $Y1 + 3] \ -text "$contestno" -fill red -tags "st $contestno"] # place some text that has the altitude displayed near the glider image set ALTITUDE($contestno) 5000 set ID($contestno) [.c.canvas create text [expr $X1 + 22] [expr $Y1 + 25] \ -text "$ALTITUDE($contestno)" -fill black -tags "st $contestno"] # this raises the gliders and their shadows above the course line .c.canvas raise st line # these lines scroll the map to center the first turnpoint where the new glider is launched. set Y1 [expr $Y1/2136] .c.canvas yview moveto $Y1 set X1 [expr $X1/1759] .c.canvas xview moveto $X1 # this adds the newly launched glider's contest no. to the list of "combatants" lappend combatants $contestno } #********************************************************************************************** proc calcdist {latdeg1a latmin1a londeg1a lonmin1a latdeg2a latmin2a londeg2a lonmin2a} { global IC set A [ expr (($latdeg1a + $latmin1a / 60) * 3.1416 / 180) ] set B [ expr (($latdeg2a + $latmin2a / 60) * 3.1416 / 180) ] set X [ expr (($londeg1a + $lonmin1a / 60) * 3.1416 /180) ] set Y [ expr (($londeg2a + $lonmin2a / 60) * 3.1416 / 180) ] set IT [ expr sin($A) * sin($B) + cos($A) * cos($B) * cos($X -$Y)] set IC [ expr 3.1416 / 2 - 2 * atan($IT / (1 + sqrt(1 - $IT * $IT)))] } #*********************************************************************************************** # this plots the course line between the two turnpoints selected see below for more info. proc plotline {latdeg1a latmin1a londeg1a lonmin1a latdeg2a latmin2a londeg2a lonmin2a} { global contestno combatants X1 Y1 X2 Y2 ALTITUDE ID shadow daystrength XAXIS YAXIS # this calculates the X Y coordinates of the two selected turnpoints and # plots a line between them on the canvas widget # upper left corner of map is 37deg 00min N. and 120deg 33min W # this is equal to 2220 and 7233 in minutes respectively # there are 14.23 pixels per minute of latitude (vertical direction) # there are 9.37 pixels per minute of longitude (horizontal direction) # this would have to be changed for each different map # but would be cool to have a routine like winGPS that could calibrate the # map by sensing the mouse position and entering two known positions # this calibrates the latitude and longitude coodinates to the pixel coordinate system # that Tcl/Tk uses for the background image. # This will have to be redone with different numbers for different maps. set X1 [ expr 7232.5 - (($londeg1a * 60) + $lonmin1a) ] set X1 [exddpr $X1 * 11.6 ] set Y1 [ expr 2222 - (($latdeg1a *60) + $latmin1a) ] set Y1 [ expr $Y1 * 13.8 ] set X2 [ expr 7232.5 -(($londeg2a * 60) + $lonmin2a) ] set X2 [ expr $X2 * 11.6 ] set Y2 [ expr 2222 -(($latdeg2a * 60) + $latmin2a) ] set Y2 [ expr $Y2 * 13.8 ] d # this puts a glider bitmap cursor over the first turnpoint selected #.c.canvas delete st .c.canvas delete rm .c.canvas delete line .c.canvas delete logo .c.canvas delete logo2 .c.canvas delete thermal .c.canvas delete strength .c.canvas delete shadow .c.canvas delete laser # draws the yellow line on the canvas after the start new leg button is pressed .c.canvas create line $X1 $Y1 $X2 $Y2 -width 3 -fill yellow -tag line # This calls the procedure that generates some random thermals and plots their position on the map # See comment above the procedure code generateThermals $X1 $Y1 $X2 $Y2 $daystrength # this places the green circles around the selected goal turnpoint .c.canvas create oval [expr $X2 - 70] [expr $Y2 - 70] [expr $X2 + 70] [expr $Y2 + 70] \ -outline green -width 2 -tags rm .c.canvas create oval [expr $X2 - 140] [expr $Y2 - 140] [expr $X2 + 140] [expr $Y2 + 140] \ -outline green -width 2 -tags rm .c.canvas create oval [expr $X2 - 210] [expr $Y2 - 210] [expr $X2 + 210] [expr $Y2 + 210] \ -outline green -width 2 -tags rm # this raises the course line above the green circles around the goal. .c.canvas raise line rm # this scrolls the map to appoximately center the first turnpoint in view. set Y1 [expr $Y1/2136] #.c.canvas yview moveto [expr $Y1/2136] .c.canvas yview moveto $Y1 set X1 [expr $X1/1759] #.c.canvas xview moveto [expr $X1/1759] .c.canvas xview moveto $X1 } #********************************************************************************* # this calculates the compass heading based on the trigonometric functions of the angles # determined by which turnpoints are selected and whether the numbers are negative or # positive which translates into east/west north/south directions. The compass variation # of 15 deg. is sdubtracted. This would be different for different locations. proc calcheading {latdeg1a latmin1a londeg1a lonmin1a latdeg2a latmin2a londeg2a lonmin2a} { global COURSE global XAXIS global YAXIS global HEADING if {[expr $latdeg2a + $latmin2a] != [expr $latdeg1a + $latmin1a]} { set YAXIS [expr (($latdeg1a * 60) + $latmin1a) - (($latdeg2a * 60) + $latmin2a)] } if {[expr $londeg2a + $lonmin2a] != [expr $londeg1a + $lonmin1a]} { set XAXIS [expr (($londeg1a * 60) + $lonmin1a) - (($londeg2a * 60) + $lonmin2a)] } if {$XAXIS != 0 } { set TN [expr $YAXIS / $XAXIS] set ANGLE [expr atan($TN) * (180 / 3.1416)] } if {$XAXIS > 0 && $YAXIS < 0} { set COURSE [expr 90 + $ANGLE - 15] if {$COURSE <= 0} { set COURSE [expr $COURSE + 360] } } if {$XAXIS > 0 && $YAXIS > 0} { set COURSE [expr 90 + $ANGLE -15] } if {$XAXIS < 0 && $YAXIS < 0} { set COURSdE [expr 270 + $ANGLE -15] } if {$XAXIS < 0 && $YAXIS > 0 } { set COURSE [expr 270 + $ANGLE -15] } if {$XAXIS == 0 && $YAXIS > 0 } { set COURSE [expr 180 -15] } if {$XAXIS == 0 && $YAXIS < 0} { set COURSE [expr 360 -15] } } #******************************************************************************* # this is used for stearing the gliders. Each frame of the animation will add or # subtract a bit to the direction of movement of the gliders in the x and y direction # depending on the value of the slider widget variable and the COURSE variable proc calcheadingchange { heading } { global XAXIS YAXIS HEADING XCHANGE YCHANGE contestno COURSE SPEED angle_radians # if heading change input is > 40 or < -40, make the glider circle # radius of circle tightens as absolute value of heading_change input increases # 100 points of the circle are plotted with each circle if {$heading_change > 40 || $heading_change < -40} { # reduce the glider speed to 0 so the circle will not continue on the course line set SPEED($contestno) 0 # increase the angle in radians to 1/100th of the number of radians in a circle set angle_radians [expr $angle_radians + (6.2332/100)] # this makes tshe glider circle to the right if the heading_change input is positive, # or right arrow input and to the left if negative, or left arrow input. if {$heading_change > 0} { set XCHANGE($contestno) [expr cos($angle_radians) * (12000/$heading_change)] set YCHANGE($contestno) [expr sin($angle_radians) * (12000/$heading_change)] } else { set XCHANGE($contestno) [expr (cos($angle_radians) * (12000/$heading_change))] set YCHANGE($contestno) [expr -(sin($angle_radians) * (12000/$heading_change))] } # return now, so the normal heading change calculations below will not be performed # when circling return } else { # if the glider has been circling, but now you decrease the steering input below # the circling threshold in order # to stop circling, set the speed back to a default value of 60kts. if {$SPEED($contestno) == 0} { set angle_radians 0 set SPEED($contestno) 60 } } # this is like for Delano to Porterville if {$XAXIS > 0 && $YAXIS < 0 } { if {$COURSE < 30} { set XCHANGE($contestno) [expr $XCHANGE($contestno) + (10 * tan($heading/57.295))] set XCHANGE($contestno) [format "%3.2f" $XCHANGE($contestno)] } else { set YCHANGE($contestno) [expr $YCHANGE($contestno) + (10 * tan($heading/57.295))] set YCHANGE($contestno) [format "%3.2f" $YCHANGE($contestno)] } } # this is like for Avenal to Delano if {$XAXIS > 0 && $YAXIS > 0} { if {$COUdRSE > 119 } { set XCHANGE($contestno) [expr $XCHANGE($contestno) - (10 * tan($heading/57.295))] set XCHANGE($contestno) [format "%3.2f" $XCHANGE($contestno)] } else { set YCHANGE($contestno) [expr $YCHANGE($contestno) + (10 * tan($heading/57.295))] set YCHANGE($contestno) [format "%3.2f" $YCHANGE($contestno)] } } # this is like for Porterville to Corcoran if {$XAXIS < 0 && $YAXIS < 0} { if {$COURSE > 290 } { set XCHANGE($contestno) [expr $XCHANGE($contestno) + (10 * tan($heading/57.295))] set XCHANGE($contestno) [format "%3.2f" $XCHANGE($contestno)] } else { set YCHANGE($contestno) [expr $YCHANGE($contestno) - (10 * tan($heading/57.295))] set YCHANGE($contestno) [format "%3.2f" $YCHANGE($contestno)] } } # this is like for Porterville to Avenal or New Cuyama if {$XAXIS < 0 && $YAXIS > 0 } { if {$COURSE < 215 } { set XCHANGE($contestno) [expr $XCHANGE($contestno) - (10 * tan($heading/57.295))] set XCHANGE($contestno) [format "%3.2f" $XCHANGE($contestno)] } else { set YCHANGE($contestno) [expr $YCHANGE($contestno) - (10 * tan($heading/57.295))] set YCHANGE($contestno) [format "%3.2f" $YCHANGE($contestno)] } } } #******************************************************************************** proc showdist {} { global IC global COURSE global TURNPOINT1 global TURNPOINT2 global autoscroll global tracking global distanceflown global contestno set COURSE [format "%3.2f" $COURSE] .turnpointframe.turnpointframe1.menu1 config -text $TURNPOINT1 .turnpointframe.turnpointframe2.menu2 config -text $TURNPOINT2 label .frame.label1 -text "distance from $TURNPOINT1 to $TURNPOINT2..." -relief groove label .frame.label3 -text "Auto Scroll ON/OFF" label .frame.label4 -text "Tracking ON/OFF" radiobutton .frame.button5 -text OFF -variable autoscroll -value off radiobutton .frafme.button6 -text " ON" -variable autoscroll -value on radiobutton .frame.button3 -text OFF -variable tracking -value off radiobutton .frame.button4 -text " ON" -variable tracking -value on label .frame.[string tolower $contestno] -text "Distance flown by $contestno -" button .frame.button7 -text "[format "%3.2f" [expr $IC * (180 / 3.1416) * (60 / .54042)]] KM" \ -relief sunken -borderwidth 3 -bg skyblue button .frame.button8 -text "[format "%3.2f" [expr $IC * (180 / 3.1416) * (60 / .8674)]] SM" \ -relief sunken -borderwidth 3 -bg skyblue button .frame.button9 -text "[format "%3.2f" [expr $IC * 60 * 180 / 3.1416]] NM" -relief sunken \ -borderwidth 3 -bg skyblue label .frame.label2 -text "Course - $COURSE deg.mag." -relief groove -bg peachpuff pack .frame.label3 pack .frame.button5 pack .frame.button6 pack .frame.label4 pack .frame.button3 pack .frame.button4 pack .frame.[string tolower $contestno] pack .frame.label1 for {set i 7} {$i <= 9 } {incr i} { pack .frame.button$i } pack .frame.label2 } #**************************************************************************** proc getcoord {} { global TURNPOINT1 global TURNPOINT2 global turnpoints global latdegrees global latmin global londegrees global lonmin global latdeg1 global latmin1 global londeg1 global lonmin1 global latdeg2 global latmin2 global londeg2 global lonmin2 set index [lsearch $turnpoints $TURNPOINT1] set latdeg1 [lindex $latdegrees $index] set latmin1 [lindex $latmin $index] set londeg1 [lindex $londegrees $index] set lonmin1 [lindex $lonmin $index] set index [lsearch $turnpoints $TURNPOINT2] set latdeg2 [lindex $latdegrees $index] set latmin2 [lindex $latmin $index] set londeg2 [lindex $londegrees $index] set lonmin2 [lindex $lonmin $index] } proc ScrolledCanvas {c width height region } { frame $c -bg red -bd 3 canvas $c.canvas -width $width -height $height \ -scrollregion $region \ -xscrollcommand [list $c.xscroll set] \ -yscrollcommand [list $c.yscroll set] scrollbar $c.xscroll -orient horizontal \ -command [list $c.canvas xview] scrollbar $c.yscroll -orient vertical \ -command [list $c.canvas yview] pack $c.xscroll -side bottom -fill x pack $c.yscroll -side right -fill y pack $c.canvas -side left -fill both -expand true pack $c -side top -fill both -expand true $c.canvas create image 1359 1836 -image sectional -anchor se $c.canvas create image 40 40 -image gliders -anchor center -tag movable $c.canvas create image 40 40 -image gliderpair -anchor center -tag movable $c.canvas bind movable <Button-1> {CanvasMark %x %y %W} $c.canvas bind movable <B1-Motion> {CanvasDrag %x %y %W} } proc CanvasMark { x y w } { global canvas # Remember the object and its location set canvas($w,obj) [$w find closest $x $y] set canvas($w,x) $x set canvas($w,y) $y } proc CanvasDrag { x y w } { # Move the current object global canvas set dx [expr $x - $canvas($w,x)] set dy [expr $y - $canvas($w,y)] $w move $canvas($w,obj) $dx $dy set canvas($w,x) $x set canvas($w,y) $y } # code for animating the glider bitmaps stolen from the Tcl Cookbook # this is the code that moves everything on the canvas display tim is the argument # that determines how fast the screen updates proc movie {tim} { global id ;# used in movie procedure to restart it after the tim interval global ID ;# array that keeps track of the altitude display for each combatant glider global XAXIS ;# the amount of movement in the x direction for each screen update global YAXIS ;# the amount of movement in the y direction for each screen update global YAXIS ;# the amount of movement in the y direction for each screen update global SPEED ;# array that holds the current speed value for each combatant ;# indexed by contestno from the combatant list global ALTITUDE ;# array that holds the current altitude for each combatant indexed by ;# contestno from the combatant list global X1 ;# the x coordinate of the first turnpoint currently selected global Y1 ;# the y coordinate of the first turnpoint currently selected global combatants ;# a list that holds the contest no's of each contestant or "combatant" global contestno ;# a simple variable that changes for each glider on the display global shadow ;# array that stores the shadows for each glider indexed by their contest no. ;# from the combatant list global HEADING ;# array that stores the heading change right or left for each glider indexed ;# by contest no from combatants list global COURSE ;# the calculated course heading between the two selected turnpoints global text ;# an array that holds each contestant's contest no. global thermals ;# list of the thermals global thermalstrength ;# array that stores the stregth of each thermal global autoscroll ;# variable that controls whether autoscrolling is enabled global tracking ;# variable that controls whether tracking is enabled global glider ;# array that stores the canvas id no.'s of the glider images global XCHANGE ;# array that stores the amount of heading change for each glider global YCHANGE ;# array that stores the amount of heading change for each glider. set headingchange 0 focus .c.canvas ;# this prevents the space bar from entering spaces in the contest No. entry box when you press it ;# to fire the projectiles # go through list of combatants and move each one and change altitude display for {set x 0} {$x < [llength $combatants]} {incr x} { set thermalfactor 0 if {[lindex $combatants $x] == ""} {continue} ;# this creates the laser missles when the spacebar is pressed bind . <KeyPress-space> ".c.canvas create line \ [expr [lindex [.c.canvas coords $glider([lindex $combatants $x])] 0] + ($XAXIS/15)] \ [expr [lindex [.c.canvas coords $glider([lindex $combatants $x])] 1] + ($YAXIS/15)] \ [expr [lindex [.c.canvas coords $glider([lindex $combatants $x])] 0] - ($XAXIS/15)] \ [expr [lindex [.c.canvas coords $glider([lindex $combatants $x])] 1] - ($YAXIS/15)] \ -width 3 -fill purple -arrow first -arrowshape {1 10 6} -tags laser " # check if the altitude has reached 0 and stop that glider, change altitude display to LANDED OUT if { $ALTITUDE([lindex $combatants $x]) > 0 } { # check to see if there has been an input to the steering slider if {$HEADING([lindex $combatants $x]) != 0} { calcheadingchange $HEADING([lindex $combatants $x]) } # this plots the track of the glider in red if tracking is enabled if {$tracking == "on"} { .c.canvas create oval [lindex [.c.canvas coords $glider([lindex $combatants $x])] 0]\ [lindex [.c.canvas coords $glider([lindex $combatants $x])] 1] \ [lindex [.c.canvas coords $glider([lindex $combatants $x])] 0] \ [lindex [.c.canvas coords $glider([lindex $combatants $x])] 1] \ -width 1 -outline red -tags track catch {.c.canvas lower track $contestno} catch {.c.canvas lower $shadow([lindex $combatants $x]) [lindex $combatants $x]} catch {.c.canvas lower track st} } # move the current glider a distance proportional to it's speed along the course direction .c.canvas move $glider([lindex $combatants $x]) \ [expr ($XCHANGE([lindex $combatants $x])/(275 - $SPEED([lindex $combatants $x])))]\ [expr ($YCHANGE([lindex $combatants $x])/(275 - $SPEED([lindex $combatants $x])))] ;# move the other objects tagged with the glider's contest no. .c.canvas move $shadow([lindex $combatants $x]) \ [expr ($XCHANGE([lindex $combatants $x])/(275 - $SPEED([lindex $combatants $x]))) - \ (.00001 * $ALTITUDE([lindex $combatants $x]))] \ [expr ($YCHANGE([lindex $combatants $x])/(275 - $SPEED([lindex $combatants $x]))) - \ (.0000075 * $ALTITUDE([lindex $combatants $x]))] .c.canvas move $ID([lindex $combatants $x]) \ [expr ($XCHANGE([lindex $combatants $x])/(275 - $SPEED([lindex $combatants $x])))] \ [expr ($YCHANGE([lindex $combatants $x])/(275 -$SPEED([lindex $combatants $x])))] .c.canvas move $text([lindex $combatants $x]) \ [expr ($XCHANGE([lindex $combatants $x])/(275 - $SPEED([lindex $combatants $x])))] \ [expr ($YCHANGE([lindex $combatants $x])/(275 - $SPEED([lindex $combatants $x])))] # this moves the laser missles .c.canvas move laser \ [expr ($XCHANGE([lindex $combatants $x])/(275 - $SPEED([lindex $combatants $x]))) + \ ($XCHANGE([lindex $combatants $x])/25)] \ [expr ($YCHANGE([lindex $combatants $x])/(275 - $SPEED([lindex $combatants $x]))) + \ ($YCHANGE([lindex $combatants $x])/25)] # check current coordinate and check to see if inside bounding box of any thermals # then adjust altitude change by thermal strength for {set y 0 } {$y < [llength $thermals]} { incr y} { set coordinates [.c.canvas coords $glider([lindex $combatants $x])] set thermalbox [.c.canvas bbox [lindex $thermals $y]] if {[lindex $coordinates 0] >= [lindex $thermalbox 0] && [lindex $coordinates 0] <= [lindex $thermalbox 2] && [lindex $coordinates 1] >= [lindex $thermalbox 1] && [lindex $coordinates 1] <= [lindex $thermalbox 3]} { set thermalfactor $thermalstrength([lindex $thermals $y]) } } # check to see if the glider has been hit by a missle foreach item [.c.canvas find withtag laser] { set coordinates [.c.canvas coords $item] set gliderbox [.c.canvas bbox $glider([lindex $combatants $x])] if {[lindex $coordinates 0] >= [lindex $gliderbox 0] && [lindex $coordinates 0] <= [lindex $gliderbox 2] && [lindex $coordinates 1] >= [lindex $gliderbox 1] && [lindex $coordinates 1] <= [lindex $gliderbox 3] && [lindex $combatants $x] != $contestno } { catch { .c.canvas itemconfigure $glider([lindex $combatants $x]) -image destroyed} catch { .c.canvas itemconfigure $shadow([lindex $combatants $x]) -image destroyedshadow} set ALTITUDE([lindex $combatants $x]) 0 .c.canvas dchars $ID([lindex $combatants $x]) 0 end .c.canvas insert $ID([lindex $combatants $x]) 0 "DESTROYED" } } set ALTITUDE([lindex $combatants $x]) [expr $ALTITUDE([lindex $combatants $x]) - \ [expr int(pow($SPEED([lindex $combatants $x]),1.8)/1000)]] # add some altitude if inside a thermal set ALTITUDE([lindex $combatants $x]) [expr $ALTITUDE([lindex $combatants $x]) + (2 * $thermalfactor)] # delete and update the altitude display for each framechange if {[.c.canvas itemcget $ID([lindex $combatants $x]) -text] != "DESTROYED"} { .c.canvas dchars $ID([lindex $combatants $x]) 0 end .c.canvas insert $ID([lindex $combatants $x]) 0 $ALTITUDE([lindex $combatants $x]) } } elseif { [.c.canvas itemcget $ID([lindex $combatants $x]) -text] != "DESTROYED"} { .c.canvas dchars $ID([lindex $combatants $x]) 0 end .c.canvas insert $ID([lindex $combatants $x]) 0 "LANDED OUT" .c.canvas delete $shadow([lindex $combatants $x]) } } # this scrolls the background map proprotional to the speed and direction of the course line if {$autoscroll == "on" } { set Y1 [expr (($YAXIS/(275 - $SPEED($contestno))) * .0007) + $Y1] .c.canvas yview moveto $Y1 set X1 [expr (($XAXIS/(275 - $SPEED($contestno))) * .0007) + $X1] .c.canvas xview moveto $X1 } set id [after $tim movie $tim] } proc displayInfo {} { global X1 Y1 global contestno global SPEED global COURSE global HEADING global XAXIS global YAXIS global XCHANGE global YCHANGE global combatants .turnpointframe.speedscale config -variable SPEED($contestno) .turnpointframe.speedscale config -label "SPEED $contestno - kts." set SPEED($contestno) 60 .turnpointframe.headingscale config -variable HEADING($contestno) .turnpointframe.headingscale config -label "Steer $contestno - L/R" set HEADING($contestno) 0 set XCHANGE($contestno) $XAXIS set YCHANGE($contestno) $YAXIS movie 250 .turnpointframe.flybutton configure -text "Stop Flying" -command \ {global id after cancel $id .turnpointframe.flybutton configure -text {The End} after 1000 .turnpointframe.flybutton configure -text "Start Flying" -command {displayInfo} } } #**************************************************************************** proc gpsdisplay1 { } { set fileid [open "test2.trk" r] seek $fileid -54 end set dataline [gets $fileid] set latitude1 [string range $dataline 4 5] set latitude2 [string range $dataline 6 10] set longitude1 [string range $dataline 16 18] set longitude2 [string range $dataline 19 23] close $fileid set X1 [ expr 7232.5 - (($longitude1 * 60) + $longitude2) ] set X1 [expr $X1 * 11.6 ] set Y1 [ expr 2222 - (($latitude1 *60) + $latitude2) ] set Y1 [ expr $Y1 * 13.8 ] .c.canvas create image $X1 $Y1 -image gliderpair -anchor center -tags st } proc gpsdisplay2 {} { global fileid global filelinenumber set filelinenumber 0 set fileid [open "test2.trk" r] while {[eof $fileid] != 1} { set a [gets $fileid] set b [eof $fileid] incr filelinenumber } set filelinenumber [expr $filelinenumber - 15] close $fileid for {set x 0} {$x < $filelinenumber} {incr x 1} { # time {set a "Hello World"} 20000 set fileid [open "test2.trk" r] set fileid [open "test2.trk" r] seek $fileid [ expr (($x * 54)+ 332)] start set dataline [gets $fileid] set latitude1 [string range $dataline 4 5] set latitude2 [string range $dataline 6 10] set longitude1 [string range $dataline 16 18] set longitude2 [string range $dataline 19 23] close $fileid set X1 [ expr 7232.5 - (($longitude1 * 60) + $longitude2) ] set X1 [expr $X1 * 11.6 ] set Y1 [ expr 2222 - (($latitude1 *60) + $latitude2) ] set Y1 [ expr $Y1 * 13.8 ] # .c.canvas create image $X1 $Y1 -image gliderpair -anchor center -tags st .c.canvas create oval [expr $X1 - 2] [expr $Y1 - 2] [expr $X1 + 2] [expr $Y1 + 2] -outline red -width 2 -tags rm } } proc gpsdisplay3 {} { global fileposition global filecounter global filelinenumber global fileid #time {set a "Hello World"} 20000 set fileid [open "test2.trk" r] while {[eof $fileid] != 1} { set a [gets $fileid] set b [eof $fileid] incr filelinenumber } set filelinenumber [expr $filelinenumber - 13] seek $fileid [ expr (($filecounter * 54)+ $fileposition)] start set filecounter [expr $filecounter + 1] set dataline [gets $fileid] set latitude1 [string range $dataline 4 5] set latitude2 [string range $dataline 6 10] set longitude1 [string range $dataline 16 18] set longitude2 [string range $dataline 19 23] set X1 [ expr 7232.5 - (($longitude1 * 60) + $longitude2) ] set X1 [expr $X1 * 11.6 ] set Y1 [ expr 2222 - (($latitude1 *60) + $latitude2) ] set Y1 [ expr $Y1 * 13.8 ] .c.canvas create image $X1 $Y1 -image gliderpair -anchor center -tags st gpsdisplay4 } proc gpsdisplay4 {} { global filecounter global filelinenumber global fileid if {$filecounter <= $filelinenumber} { set filelinenumber 0 gpsdisplay3 } else { set filecounter 0 set filelinenumber 0 close $fileid } } # The code to generate some random thermals of random strength in the area # of the bounding box associated with the line that represents the course # line of the current leg which is created in the plotline procedure proc generateThermals {X1 Y1 X2 Y2 daystrength} { global thermals thermalstrength # this makes sure that there is always one tiny thermal, then even if you by chance get 0 for the random no. of thermals, # the proc won't crash. set ID1 [.c.canvas create oval 1 3 5 7 -fill black -stipple gray12] lappend thermals $ID1 # attempt to generate a set of thermals randomly - the number, strength and size in area are all set # separately but have a higher chance of being more numerous and stronger depending on the daystrength # variable that the user can set. for {set x 0} {$x < [RandomRange $daystrength]} {incr x} { # find out the lengths of the sides of the bounding box of the course line - all the thermals will be in # this area only, prevents plotting thermals where you are never going to fly for the current course. set xrange [expr $X2 - $X1] set yrange [expr $Y2 - $Y1] # this calculates the upper left and lower right corners of the bounding box for each thermal oval ;# this calculates the upper left and lower right corners of the bounding box for each thermal oval set bboxx1 [expr $X1 + [RandomRange $xrange]] set bboxy1 [expr $Y1 + [RandomRange $yrange]] # this actually plots the thermal ovals in the randomly generated positions determined above # the size is a random range up to 100 pixels but you could set this to a different number if desired. # set ID2 [.c.canvas create oval $bboxx1 $bboxy1 [expr $bboxx1 + [RandomRange 100]] [expr $bboxy1 + \ [RandomRange 100]] -fill black -stipple gray12 -tag thermal] set ID2 [.c.canvas create image [expr $bboxx1 + [RandomRange 100]] [expr $bboxy1 + \ [RandomRange 100]] -image dustdevil -tag thermal] # this adds the id no. of each thermal to the list thermals for later querying when a glider flies into it's bounding box # the value of the thermal's strength can be queried. lappend thermals $ID2 # this sets the thermal strength to a random value but max is determined by the user controllable daystrength variable set thermalstrength($ID2) [RandomRange $daystrength] if {$thermalstrength($ID2) == 0 } {set thermalstrength($ID2) 1} .c.canvas scale $ID2 [lindex [.c.canvas coords $ID2] 0] [lindex [.c.canvas coords $ID2] 1] \ $thermalstrength($ID2) $thermalstrength($ID2) # this plots a text representation of the thermal's strength in the upper left corner of the thermal's bounding box .c.canvas create text [lindex [.c.canvas coords $ID2] 0] [lindex [.c.canvas coords $ID2] 1] \ -text "$thermalstrength($ID2)" -fill red -tags strength } } # the code for the bitmap display for the small glider images - supposed to be # an AS-H 25. The first one is for a glider flying southeast. set g {R0lGODdhXQBbAPUAAAAAAP///1WSVf+SqgBJVVVJAFVJ/6q2VQAkqlUkVVVtqlWS/6ptVaqS qv+2/wAAVQBJAABJ/1VJqlVtAKpJVaq2qv+2Vf+2qgAkAAAkVQBJqlUkAFVJVVVtVVVt/1WS qqptqqqSVarbqqrb///bqv/b/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAAXQBbAAAG /kCAcEgsGo/IpHLJbDqf0Kh0Sq1ar9isdsvter/gsHhMLpvP4wsGzU4yOu14EXOR24UX+D3e OOzjBBYZf20XFYRsISRriGYJFSGNZxVqkmUMInqWXQpEGJSbXg2aAAMHHKFdJUQcFSSpXBWk FweMsEakTQSrQw0WDbdHDZFQJRNDBa7BRopRIbxCrqjLQ60btk0jmiGG1ERqDdNNFdAblNjU qB3ETB0lmpQC3rgM4koj0CGg80Uc60wNSOjhcOECBH5zCnBY8wBCAoX+IuKDYMiQAAkIMjxA yGTDtRIC3xygdEBBBxAKNGSwx9FIAxG8CjS4MIEDBwofOjCot6Hl/hEMJUowonQIADqfSC6M KNqqEqxOVxSAFELn1K0QwK6IIAFV3ytY7o5GaVBihBCCFcQSSrArl5QMMAsIUcTS0rtBVkiU EDG3QtFU8Rr0pMIAnxAIAQeHagUARIcGapmA/ICnglxYBITo/FB3nIgAQhjsW0bA8agoHMrK TSDCQmRJGPw1EACicxIHMIUcuICXHweHZ6dBTmBTdoC9JRREMKBhgUakP4UQ2KBAALkKHyRo qOBBgQcNCmxDB7A3bUQQAroraFAh6/hvIhwIGYwtw+uWDfCtweCA3fskIMB0EAAB/bcEUH7N l5aBSuAmXzQMMJhEBTAxwoEFEiLBnlBDYXyVYT8VDhHCff9dx8qHRpSHohIvQbOiS/GRmGGI Lx5RlngrVjBChDW6BEmPuCQIpCcluDekEA78dSQAQi4JQAdKHgmUjBly6OSVWGap5ZZcdunl l2CGKeaYZJZp5plgBgEAOw} # this one is for a glider flying about due west set west { #define west_width 42 #define west_height 52 static char west_bits[] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00, 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00, 0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00, 0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00, 0x60,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00, 0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00, 0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x06,0x00, 0x00,0x08,0x00,0x00,0x0e,0x00,0x00,0x10,0x00,0x00,0x0c,0x00,0x00,0x20,0x00, 0x00,0x1c,0x00,0x00,0x60,0x00,0x00,0x18,0x00,0x00,0xf0,0x00,0x00,0x30,0x00, 0x00,0xb8,0x01,0x00,0x70,0x00,0x00,0x1c,0x03,0x00,0x60,0x00,0x00,0x1e,0x00, 0x00,0xe0,0xff,0xff,0x0f,0x00,0x00,0xfe,0xff,0x1f,0x00,0x00,0xc0,0xff,0x0f, 0x00,0x00,0x00,0xf0,0x7f,0x03,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, 0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x00,0x1c, 0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00, 0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0xc0, 0x01,0x00,0x00,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00, 0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00, 0x18,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00, 0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00, 0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x02,0x00, 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x08,0x00}; } # this one is for a glider flying northeast set northeast { #define northeast_width 30 #define northeast_height 57 static char northeast_bits[] = { 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x07,0x00,0x00,0x00, 0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x18,0x00,0x00, 0x00,0x38,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x70,0x00,0x02,0x00,0x60,0x00, 0x02,0x00,0xe0,0x80,0x01,0x00,0xc0,0xc0,0x01,0x00,0x80,0xf1,0x00,0x00,0x80, 0x73,0x00,0x00,0x00,0x7b,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x3e,0x00,0x00, 0x00,0x1f,0x00,0x00,0x00,0x07,0x00,0x00,0x80,0x1f,0x00,0x00,0x80,0x1b,0x00, 0x00,0xc0,0x1b,0x00,0x00,0xc0,0x38,0x00,0x00,0x60,0x30,0x00,0x00,0x70,0x78, 0x00,0x00,0x30,0x60,0x00,0x00,0x38,0x60,0x00,0x00,0x18,0x60,0x00,0x00,0x0c, 0xc0,0x00,0x00,0x04,0xc0,0x01,0x01,0x02,0x80,0x01,\,0x03,0x80,0x03,0xf0, 0x01,0x80,0x01,0xfe,0x00,0x00,0x02,0xee,0x00,0x00,0x03,0x06,0x00,0x00,0x03, 0x04,0x00,0x00,0x02,0x0c,0x00,0x00,0x0c,0x04,0x00,0x00,0x0c,0x00,0x00,0x00, 0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x18,0x00,0x00, 0x00,0x10,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x20}; } # this one is for a glider flying southwest set southwest { #define southwest_width 61 #define southwest_height 29 static char southwest_bits[] = { 0x00,0x00,0x00,0x00,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4e,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00, 0x00,0x80,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x60,0x00, 0x00,0x00,0x70,0x00,0x00,0x00,0xc0,0x06,0x00,0x00,0x30,0x00,0x00,0x00,0x00, 0x1e,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0xf8,0x01,0x00,0x1e,0x00,0x00,0x00, 0x00,0x80,0x0f,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x3d,0x80,0x01,0x00,0x00, 0x00,0x00,0x00,0xec,0xc2,0x01,0x00,0x00,0x00,0x00,0x00,0xe0,0xf7,0x01,0x00, 0x00,0x00,0x00,0x00,0x00,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x9f, 0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x1e, 0xf8,0x9f,0x00,0x00,0x00,0x00,0x00,0x1f,0x00,0xfe,0x07,0x00,0x00,0x00,0x00, 0x07,0x00,0xa0,0x6e,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0xf0,0x13,0x00,0x00, 0xc0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x40,0x00,0x00,0x00,0x00,0x00}; } # this one is for a destroyed glider set destroyed { #define destroyed_width 29 #define destroyed_height 61 static unsigned char destroyed_bits[] = { 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0xc0, 0x1f, 0x01, 0x00, 0xc0, 0x10, 0x01, 0x00, 0xc0, 0x10, 0x03, 0x00, 0xe0, 0x00, 0x0f, 0x00, 0xe0, 0x00, 0x0c, 0x00, 0x60, 0x00, 0x18, 0x00, 0x60, 0x00, 0x30, 0x00, 0xe0, 0x00, 0x40, 0x40, 0x60, 0x00, 0x80, 0x67, 0x30, 0x00, 0x00, 0x7f, 0x30, 0x00, 0x00, 0x7f, 0x30, 0x00, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x80, 0x02, 0x06, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x1e, 0x03, 0x00, 0x00, 0x3c, 0x07, 0x00, 0x00, 0x78, 0x03, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xc0, 0x03}; } set dustdevil { #define dustdevil_width 81 #define dustdevil_height 89 static char dustdevil_bits[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x28,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, 0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x40,0x4c,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x82,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0c,0xb6,0x01, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x05,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x64,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80, 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x99,0x13,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0xac,0x52,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x10,0x0a, 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xc0,0x0a,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x20,0xf4,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x22,0x0c,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x90,0x02,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0x5a,0x15,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x20,0xd3,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0, 0x21,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0xa2,0x52,0x01,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x9d,0x21,0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x40,0x41,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x8a,0x05, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x3a,0x08,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xa6,0xa9,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10, 0x28,0x59,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0xfa,0x2b,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x40,0x40,0xa0,0x02,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x20,0x62,0xa9,0x25,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x58,0x29, 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xa9,0x15,0x0a,0x00,0x00,0x00, 0x00,0x00,0x00,0xa0,0xed,0xef,0x95,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x20, 0xf8,0xaf,0xa0,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x9c,0x39,0x22,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xeb,0xe2,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0xa0,0x3b,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x3f, 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x7e,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0xf2,0x3e,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0xfe,0x2b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfd,0x27,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0x0f,0x06,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xfe,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xfe,0x17,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x7d,0x87,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xfe,0x0f,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x40,0xfd,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf2, 0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xf6,0x07,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0xbb,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xbe,0x05, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x40,0x7a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x40,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xfe,0x07,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xf6,0x01,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xda,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40, 0x7f,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfd,0x01,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xdf,0x01,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x7e,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xee, 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xff,0x01,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0xfb,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x01, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xee,0x01,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0xdf,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0xfe,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x01,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xf6,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xf6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xce,0x01,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x01,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x40,0x7f,0x12,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xfd, 0x05,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x5d,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0xe4,0x7d,0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0xfd,0xaf,0xbe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd9,0x6b,0xbe, 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7d,0x7c,0xf7,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00}; } set bmp { #define pic45tra_width 93 #define pic45tra_height 91 static unsigned char pic45tra_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc3, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; } # Main Body of Program # next two lines create the images use for non plugin version comment out for plugin version image create photo sectional -file largeclr.gif -gamma 1 image create photo gliders -file pic45tra.gif -gamma 1 # uncomment next 2 lines for plugin version (non plugin can't use -data statement) #image create photo gliders -data $g #image create photo sectional -date $i # bitmaps work with -data in both versions image create bitmap gliderpair -data $bmp -foreground white image create bitmap gliderpairwest -data $west -foreground white image create bitmap glidershadow -data $bmp -foreground gray50 image create bitmap glidershadowwest -data $west -foreground gray50 image create bitmap gliderpairnortheast -data $northeast -foreground white image create bitmap glidershadownortheast -data $northeast -foreground gray50 image create bitmap gliderpairsouthwest -data $southwest -foreground white image create bitmap glidershadowsouthwest -data $southwest -foreground gray50 image create bitmap destroyed -data $destroyed -foreground white image create bitmap destroyedshadow -data $destroyed -foreground gray50 image create bitmap dustdevil -data $dustdevil -foreground brown ScrolledCanvas .c 400 300 { 0 0 1359 1836 } frame .frame ;#frame for holding the great circle distance calculation pack .frame #******************************************************************************* getturnpoint ;#procedure to get the index value of the selected turnpoints #bind . <KeyPress-Left> {set SPEED(IB) [expr $SPEED(IB) - 1]} getcoord ;#gets the coordinates from the list for the selected turnpoints calcdist $latdeg1 $latmin1 $londeg1 $lonmin1 $latdeg2 $latmin2 $londeg2 $lonmin2 calcheading $latdeg1 $latmin1 $londeg1 $lonmin1 $latdeg2 $latmin2 $londeg2 $lonmin2 #plotline $latdeg1 $latmin1 $londeg1 $lonmin1 $latdeg2 $latmin2 $londeg2 $lonmin2 #set HEADING($contestno) $COURSE showdist .c.canvas yview moveto .45 .c.canvas xview moveto .1 .c.canvas create text [expr 400 + 105] [expr 1025 - 45] -text "Glider Combat!!!" \ -font -freefont-futura_poster-*-r-*-*-*-400-*-*-*-*-*-* -fill black -tags logo .c.canvas create text [expr 400 + 95] [expr 1025 - 55] -text "Glider Combat!!!" \ -font -freefont-futura_poster-*-r-*-*-*-400-*-*-*-*-*-* -fill olivedrab -tags logo2 .c.canvas create text [expr 400 + 110] [expr 1025 - 10] -text "by Alex Caldwell" \ -font -freefont-futura_poster-*-r-*-*-*-400-*-*-*-*-*-* -fill purple -tags logo # End of Program
Alex Caldwell 2003-06-15: I added some code to the calcheadingchange proc that now enables the gliders to circle in thermals, instead of just making "S" turns. New global variable "angle_radians" added that gets increased by .01 x the number of radians in a circle with each frame until the steering input decreases back below the circling threshold. When the steering input value reaches a threshold of absolute value 40 or more, the glider will circle right or left depending on left arrow or right arrow input. The radius of the circle decreases proportional to the absolute value of the steering input.
AMG: This code seems to have suffered some form of bit rot. Running in Tcl 8.6.4, I get this error:
format error in bitmap data while executing "image create bitmap gliderpair -data $bmp -foreground white" (file "./sailplane.tcl" line 1338)Apparently there's a bitmap format incompatibility. I have no time to investigate now, just reporting the issue.