|
Post by carlgundel on Aug 13, 2018 19:35:14 GMT
Add a mode to the lander.bas example that comes with Liberty BASIC which automatically controls the rotation and thrust of the lander to automatically land it safely.
|
|
|
Post by B+ on Nov 27, 2018 16:42:00 GMT
I have started working on this challenge yesterday and have HAL, the auto pilot, working so that you can toggle it on and off and it is helpful getting speed down and lander oriented, but don't have it recognizing safe landing zones yet, so you have to take over if you are not dropping/drifting over to a site.
In meantime, while testing game for many rounds the whole program will unceremoniously shut down, with blue swirl (wait) circle that MS Windows plays to wait for something (about 1.5 secs), then everything closes both the graphics window AND Just Basic IDE AND no error is recorded in Error.log.
Here is work-in-progress with shut-down problem usually striking after 3 to 5 rounds.
'Lander mod Auto mode.txt for JB v2 B+ started 2018-11-26 Post problem 2018-11-27 ' 2018-11-26 build from Lander mod 2.txt for JB v2 B+ 2018-05-29 ' fix code and comment better, fix error /crash when lander beyond LANDH limits ' fix left arrow when VDA goes below 0
' which was built from: ' Lander by Carl mod Rod mod B+.bas for JB v2 started 2018-05-26 ' from Rod's mod of Lander.bas written by Carl Gundel ' carlg@world.std.com ' Needs at least Liberty BASIC v2.0 ???? ' This file is contributed to the public domain ' ' ======================== INSTRUCTIONS ============================ ' ' Objective: You must make a VERY gentle and level landing on one of ' the flat areas with Lander in upright angle! ' ' Use the left or right arrow keys to rotate lander left or right ' Use the up arrow for forward Thrust ' NEW HERE! Use the "a" key to toggle auto pilot on and off ' '===================================================================
' globals all caps for easier code reading ' note: D stands for Delta the nerdy way to say change
' CONSTANTS global XMAX, YMAX, PI, D2R, DG, DAT XMAX = 800 'width drawing area needed YMAX = 600 'height of drawing area PI = acs(-1) 'constant pi D2R = PI / 180 'convert angle in degrees to radians DG = .1 'this is the constant change in vertical speed due to gravity DAT = 2 'this is constant change of Acceleration when thrust has been applied
' GLOBAL VARIABLES for the subs dim LANDH(XMAX), LZX(15), LZY(15) 'array tracks y heights of land across the screen (x) global FUEL, SPEED, VDA, VX, VY, DX, DY 'for locating the Lander commented in [startGame] global LZI, AUTO, STAGE 'for toggle of Auto Pilot
nomainwin WindowWidth = XMAX + 8 WindowHeight = YMAX + 32 UpperLeftX = int((DisplayWidth-WindowWidth)/2) UpperLeftY = int((DisplayHeight-WindowHeight)/2)
graphicbox #lander.fuel 10,10,10,500 open "Lunar Lander with Auto Pilot Toggle (key a)" for graphics_nsb as #lander #lander "trapclose quit" ' set end program code #lander "when characterInput control" ' set keypress code #lander "setfocus" ' catch keypresses see sub control
call makeSprites 'this sets up the lander image call startGame wait
sub startGame ' (re)initialize redraw and reset setting and game variables LZI = 0 ' track landing zone index call setBackground 'make landing scene and record surface heights of land in LANDH() #lander "spritexy lem 50 50" #lander.fuel "down ; fill red ; size 4 ; north ;color yellow" FUEL = 500 ' this is the space vehicle's fuel SPEED = 6 ' this is the speed the vehicle is moving in the VDA direction VDA = 0 ' VDA is vehicle degree angle = orientation of the vehicle, 0 = pointed right due East VX = 50 ' this is current x position of vehicle 10 pixles from left side VY = 10 ' this is current y position of vehicle 10 pixels down from top of screen DX = SPEED * cos(D2R * VDA) ' this is the horizontal x change on screen due to speed and angle DY = SPEED * sin(D2R * VDA) ' this is the vertical y change on screen due to speed and angle
'new for HAL the auto pilot, AUTO will also track what stage HAL has advanced to between TIMER calls AUTO = 0 ' HAL the Auto Pilot sub will be toggled on /off with A or a keypress TARGETX = 0 ' Target x aquired if <> 0 timer 100, timerTicked ' update Lander with the above variables end sub
sub quit H$ timer 0 close #lander end end sub
sub timerTicked 'This is the main display of simulation timer 0
if AUTO then call HAL ' is HAL landing the craft?
'vehicle falls faster and faster, because gravity effects the vertical speed DY = DY + DG 'speed up falling due to gravity acceleration
'new position = last postion plus the horizontal and vertical changes from momentum VX = VX + DX VY = VY + DY
if VX < 20 or VX > XMAX - 15 or VY < -100 then notice "You have drifted off screen." : call askGoAgain end if
if VY <= LANDH(VX + 15) - 24 and FUEL > 0 then #lander "cls" #lander "discard" #lander "spriteimage lem lem"; int(VDA / 22.5) ' pull up the sprite angled closest to VDA #lander "spritexy lem "; VX; " "; VY ' locate on screen #lander "drawsprites" ' show background and lander #lander.fuel "cls ;fill red ;place 4 500 ; go ";FUEL ' show fuel usage call label "white", "black", 5, 570, "HAL: ";AUTO call label "white", "black", 105, 570, "VDA: ";VDA call label "white", "black", 205, 570, "DX: ";int(DX*1000)/1000 call label "white", "black", 305, 570, "DY: ";int(DY*1000)/1000 timer 100, timerTicked ' restart timer else crash$ = "" if VDA <> 90 then crash$ = "Vehicle not upright. " if DY > 4 then crash$ = crash$ + "Came down too fast. " if DX > 4 then crash$ = crash$ + "Still moving hoizontally too fast. " if FUEL <= 0 then crash$ = crash$ + "Ran out of fuel. " if LANDH(VX + 7) <> LANDH(VX + 22) then crash$ = crash$ + "Did not land on level site. " if crash$ <> "" then cause$ = "You crashed!" + chr$(13) + crash$ notice cause$ else notice "Successful landing!"+ chr$(13) + "You lived to land again!" end if call askGoAgain end if #lander "flush" end sub
sub askGoAgain timer 0 confirm "Try again?"; answer if answer then call startGame else call quit "l" end sub
sub control H$, k$ key = asc(right$(k$, 1)) select case key case 65, 97 : if AUTO then AUTO = 0 else AUTO = 1 case _VK_UP : call forwardThrust case _VK_LEFT : call rotateLeft case _VK_RIGHT : call rotateRight end select end sub
sub forwardThrust 'separate from Control so HAL can access thruster 'here is the vertical and horizontal change from a burst of fuel for thrust thrustx = DAT * cos(D2R * VDA + PI) thrusty = DAT * sin(D2R * VDA + PI) 'now change the horizontal and vertical momentums from the thrust DX = DX + thrustx DY = DY + thrusty 'update the position VX = VX + DX VY = VY + DY 'the thrust cost fuel FUEL = FUEL - 10 end sub
sub rotateRight 'separate from Control so HAL can access VDA = VDA + 22.5 if VDA > 337.51 then VDA = 0 FUEL = FUEL - 10 end sub
sub rotateLeft 'separate from Control so HAL can access VDA = VDA - 22.5 if VDA < -0.01 then VDA = VDA + 360 FUEL = FUEL - 10 end sub
sub HAL 'NEW, HAL is the Happy Auto-pilot Lander program 'HAL is allowedup to 1 command to control module for ajusting the trajectory 'first priority is get upright or nearly so thrusters
'get DX speed down fast as possible and keep lem up high if DY > 0 and abs(DX) > .5 then 'thrust up and left or right if DX < .5 then 'get VDA to 135 before applying forward thrust if VDA >=0 and VDA < 135 then call rotateRight : exit sub if VDA >=315 and VDA < 360 then call rotateRight : exit sub if VDA > 135 and VDA < 315 then call rotateLeft : exit sub call forwardThrust : exit sub else if DX > .5 then 'get VDA to 45 before applying forward thrust if VDA >= 0 and VDA < 45 then call rotateRight : exit sub if VDA > 225 and VDA < 360 then call rotateRight : exit sub if VDA > 45 and VDA <= 225 then call rotateLeft : exit sub call forwardThrust : exit sub end if end if end if
'drop but not too fast if DY > 3.5 then if DX < -1 then if VDA < 90 then call rotateRight : exit sub call forwardThrust : exit sub end if if DX > 1 then if VDA > 90 then call rotateLeft : exit sub call forwardThrust : exit sub end if if VDA < 90 then call rotateRight : exit sub if VDA > 90 then call rotateLeft : exit sub call forwardThrust : exit sub end if
end sub
sub makeSprites open "lem" for graphics as #makeSprites #makeSprites "down" #makeSprites "place 0 31 ; backColor black ; boxfilled 640 73" for x = 0 to 15 y = 1 call drawLEM x, y, 270 + x * 22.5, 2, "black" y = 2 call drawLEM x, y, 270 + x * 22.5, 2, "darkgray" call drawLEM x, y, 270 + x * 22.5, 1, "lightgray" call getSprite x next x close #makeSprites #lander "addsprite lem lem0 lem1 lem2 lem3 lem4 lem5 lem6 lem7 lem8 lem9 lem10 lem11 lem12 lem13 lem14 lem15" end sub
sub drawLEM xPosition, yPosition, uncorrectedAngle, penSize, color$ angle = uncorrectedAngle #makeSprites "north ; color "; color$; " ; up ; turn "; angle #makeSprites "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #makeSprites "size "; penSize #makeSprites "up ; go 4 ; down ; circlefilled 8" #makeSprites "turn 75 ; go 4 ; turn 180 ; go 4" #makeSprites "turn 30 ; go 4 ; turn 180 ; go 4 ; turn 255" #makeSprites "up ; turn 160 ; go 8" #makeSprites "down ; go 4 ; turn 110" #makeSprites "go 8 ; turn 110 ; go 4" #makeSprites "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #makeSprites "north ; up ; turn "; angle #makeSprites "go 4 ; turn 125 ; go 8 ; down ; turn 45 ; go 8" #makeSprites "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #makeSprites "north ; up ; turn "; angle #makeSprites "go 4 ; turn 235 ; go 8 ; down ; turn -45 ; go 8" end sub
sub setBackground #lander "down ; fill black" 'stars for s = 1 to 100 c=int(rnd(0)*100+156) #lander "color ";c;" ";c;" ";c #lander "size ";int(rnd(0)*4) #lander "set ";rnd(0)*800;" ";rnd(0)*600 next call drawTerrain #lander "getbmp stars 0 0 800 600" #lander "background stars" end sub
sub getSprite spritNum spriteX = spritNum * 30 #makeSprites "getbmp lem"; spritNum; " "; spriteX; " 1 30 60" end sub
sub drawTerrain rate1 = rnd(1) / (rnd(1) * 10 + 5) rate2 = rnd(1) / (rnd(1) * 5 + 5) #lander "down ; size 1 ; color white" for x = 0 to XMAX if rnd(1) < 0.015 then gosub [makeLandingZone] holder1 = holder1+rate1 holder2 = holder2+rate2 holder3 = holder3+sin(holder2)/20 y = 400+int(sin(holder1)*50)+int(cos(holder2)*50)+int(cos(holder3)*15) LANDH(x) = y c=rnd(0)*50+50 #lander "color ";c;" ";c;" ";c;" ; line ";x;" 600 ";x; " ";y next x exit sub
[makeLandingZone] width = int((rnd(1)*4+2)/2) for lz = x to min(799, x + 34 * width) LANDH(lz) = y c=rnd(0)*50+50 #lander "color ";c;" ";c;" ";c;" ; line ";lz;" 600 ";lz; " ";y next lz #lander "size 2" #lander "color yellow ; line ";x;" ";y;" ";lz;" ";y #lander "size 1" if LZI < 15 then 'new, save landing zone data for HAL "to see" LZI = LZI + 1 LZX(LZI) = x + int(.5 * width) : LZY(LZI) = y end if x = lz return end sub
sub label fColor$, bColor$, x, y, text$ #lander "color ";fColor$ #lander "backcolor ";bColor$ #lander "place ";x;" ";y #lander "boxfilled ";x + 8 * len(text$) + 10;" ";y + 20 #lander "place ";x + 5;" ";y + 15;";\";text$ end sub
BTW, the VDA, Vehicle Degree Angle = orientation of lander, has 90 degrees due North, and 0 degrees due West not East, angle increases in clockwise direction (right arrow on keyboard) and decreases in counterclockwise direction (left arrow on keyboard).
I would guess the issue is a memory management problem because no problem arises just playing a couple of games. I tried adding "cls" and "discard" and "flush" but don't know enough about memory for effective placement from which to call them.
|
|
|
Post by carlgundel on Nov 27, 2018 18:35:54 GMT
I have started working on this challenge yesterday and have HAL, the auto pilot, working so that you can toggle it on and off and it is helpful getting speed down and lander oriented, but don't have it recognizing safe landing zones yet, so you have to take over if you are not dropping/drifting over to a site. In meantime, while testing game for many rounds the whole program will unceremoniously shut down, with blue swirl (wait) circle that MS Windows plays to wait for something (about 1.5 secs), then everything closes both the graphics window AND Just Basic IDE AND no error is recorded in Error.log. Here is work-in-progress with shut-down problem usually striking after 3 to 5 rounds. <....> I would guess the issue is a memory management problem because no problem arises just playing a couple of games. I tried adding "cls" and "discard" and "flush" but don't know enough about memory for effective placement from which to call them. That's exciting that you've taken a stab at it! I'll try to have a look at it later today.
|
|
|
Post by B+ on Nov 27, 2018 23:08:47 GMT
Hmm... just had a run of 21 rounds before the blue circle closed everything down. ?
|
|
|
Post by carlgundel on Nov 27, 2018 23:41:26 GMT
Hmm... just had a run of 21 rounds before the blue circle closed everything down. ? No crashes yet, but I recommend you get rid of the #lander "cls" line in the timerTicked routine. Clearing the display should not be necessary, and it defeats the flicker free purpose of using sprites. Also, the autopilot works pretty well. Congratulations!
|
|
|
Post by B+ on Nov 28, 2018 0:36:25 GMT
Thanks Carl,
I tried "cls" because I read something in Help about it releasing memory. But you are right, it was better before trying it.
|
|
|
Post by carlgundel on Nov 28, 2018 0:41:56 GMT
Thanks Carl, I tried "cls" because I read something in Help about it releasing memory. But you are right, it was better before trying it. The discard command will release drawing commands that have not been flushed, so if you draw a bunch of stuff each timer tick and then use discard without flush, you should be good.
|
|
|
Post by B+ on Nov 28, 2018 5:21:32 GMT
HAL is now targeting Landing zones, gets in pretty close, with just a little human help should be safe landing every time (unless no landing zones until right 1/3 of screen which rarely happens).
'Lander mod Auto mode.txt for JB v2 B+ started 2018-11-26 post 2018-11-28 ' 2018-11-26 build from Lander mod 2.txt for JB v2 B+ 2018-05-29 ' which was built from: ' Lander by Carl mod Rod mod B+.bas for JB v2 started 2018-05-26 ' from Rod's mod of Lander.bas written by Carl Gundel ' carlg@world.std.com ' Needs at least Liberty BASIC v2.0 ???? ' This file is contributed to the public domain ' ' Development Notes: ' 2018-11-26 fix code and comment better, fix error /crash when lander beyond LANDH limits ' fix left arrow when VDA goes below 0 ' HAL code started with slow downs of DX and DY dropping and keeping upright ' 2018-11-27 Post, report the crashing problem after a 2 - 21 rounds played. ' 2018-11-28 Post, HAL now does Landing zone spotting and targeting now, pretty close! ' ' ======================== INSTRUCTIONS ============================ ' ' Objective: You must make a VERY gentle and level landing on one of ' the flat areas with Lander in upright angle! ' ' Use the left or right arrow keys to rotate lander left or right ' Use the up arrow for forward Thrust ' NEW HERE! Use the "a" key to toggle auto pilot on and off ' '===================================================================
' globals all caps for easier code reading ' note: D stands for Delta the nerdy way to say change
' CONSTANTS global XMAX, YMAX, PI, D2R, DG, DAT XMAX = 800 'width drawing area needed YMAX = 600 'height of drawing area PI = acs(-1) 'constant pi D2R = PI / 180 'convert angle in degrees to radians DG = .1 'this is the constant change in vertical speed due to gravity DAT = 2 'this is constant change of Acceleration when thrust has been applied
' GLOBAL VARIABLES for the subs dim LANDH(XMAX), LZX(15), LZY(15) 'array tracks y heights of land across the screen (x) global FUEL, SPEED, VDA, VX, VY, DX, DY 'for locating the Lander commented in [startGame] global LZI, AUTO, TARGET 'for toggle of Auto Pilot global LANDINGS, CRASHES
nomainwin WindowWidth = XMAX + 8 WindowHeight = YMAX + 32 UpperLeftX = int((DisplayWidth-WindowWidth)/2) UpperLeftY = int((DisplayHeight-WindowHeight)/2)
graphicbox #lander.fuel 10,10,10,500 open "Lunar Lander with Auto Pilot Toggle (key a)" for graphics_nsb as #lander #lander "trapclose quit" ' set end program code #lander "when characterInput control" ' set keypress code #lander "setfocus" ' catch keypresses see sub control
call makeSprites 'this sets up the lander image call startGame wait
sub startGame ' (re)initialize redraw and reset setting and game variables LZI = 0 ' track landing zone index call setBackground 'make landing scene and record surface heights of land in LANDH() #lander "spritexy lem 50 50" #lander.fuel "down ; fill red ; size 4 ; north ;color yellow" FUEL = 500 ' this is the space vehicle's fuel SPEED = 6 ' this is the speed the vehicle is moving in the VDA direction VDA = 0 ' VDA is vehicle degree angle = orientation of the vehicle, 0 = pointed right due East VX = 50 ' this is current x position of vehicle 10 pixles from left side VY = 10 ' this is current y position of vehicle 10 pixels down from top of screen DX = SPEED * cos(D2R * VDA) ' this is the horizontal x change on screen due to speed and angle DY = SPEED * sin(D2R * VDA) ' this is the vertical y change on screen due to speed and angle
'new for HAL the auto pilot, AUTO will also track what stage HAL has advanced to between TIMER calls AUTO = 0 ' HAL the Auto Pilot sub will be toggled on /off with A or a keypress TARGET = 0 ' Target x aquired if <> 0 timer 100, timerTicked ' update Lander with the above variables end sub
sub quit H$ timer 0 close #lander end end sub
sub timerTicked 'This is the main display of simulation timer 0
if AUTO then call HAL ' is HAL landing the craft?
'vehicle falls faster and faster, because gravity effects the vertical speed DY = DY + DG 'speed up falling due to gravity acceleration
'new position = last postion plus the horizontal and vertical changes from momentum VX = VX + DX VY = VY + DY
if VX < 20 or VX > XMAX - 15 or VY < -100 then notice "You have drifted off screen." : call askGoAgain end if
if VY <= LANDH(VX + 15) - 24 and FUEL > 0 then #lander "discard" #lander "spriteimage lem lem"; int(VDA / 22.5) ' pull up the sprite angled closest to VDA #lander "spritexy lem "; VX; " "; VY ' locate on screen #lander "drawsprites" ' show background and lander #lander.fuel "cls ;fill red ;place 4 500 ; go ";FUEL ' show fuel usage call label "white", "black", 5, 570, "HAL: ";AUTO;" LZ# ";TARGET call label "white", "black", 130, 570, "VDA: ";VDA call label "white", "black", 255, 570, "DX: ";int(DX*1000)/1000 call label "white", "black", 380, 570, "DY: ";int(DY*1000)/1000 call label "white", "black", XMAX - 300, 570, "LANDINGS: ";LANDINGS call label "white", "black", XMAX - 150, 570, "CRASHES: ";CRASHES timer 100, timerTicked ' restart timer else crash$ = "" if VDA <> 90 then crash$ = "Vehicle not upright. " if DY > 4 then crash$ = crash$ + "Came down too fast. " if DX > 4 then crash$ = crash$ + "Still moving hoizontally too fast. " if FUEL <= 0 then crash$ = crash$ + "Ran out of fuel. " if LANDH(VX + 7) <> LANDH(VX + 22) then crash$ = crash$ + "Did not land on level site. " if crash$ <> "" then cause$ = "You crashed!" + chr$(13) + crash$ CRASHES = CRASHES + 1 notice cause$ else LANDINGS = LANDINGS + 1 notice "Successful landing!"+ chr$(13) + "You lived to land again!" end if call askGoAgain end if #lander "flush" end sub
sub askGoAgain timer 0 confirm "Try again?"; answer if answer then call startGame else call quit "l" end sub
sub control H$, k$ key = asc(right$(k$, 1)) select case key case 65, 97 : if AUTO then AUTO = 0 else AUTO = 1 case _VK_UP : call forwardThrust case _VK_LEFT : call rotateLeft case _VK_RIGHT : call rotateRight end select end sub
sub forwardThrust 'separate from Control so HAL can access thruster 'here is the vertical and horizontal change from a burst of fuel for thrust thrustx = DAT * cos(D2R * VDA + PI) thrusty = DAT * sin(D2R * VDA + PI) 'now change the horizontal and vertical momentums from the thrust DX = DX + thrustx DY = DY + thrusty 'update the position VX = VX + DX VY = VY + DY 'the thrust cost fuel FUEL = FUEL - 10 end sub
sub rotateRight 'separate from Control so HAL can access VDA = VDA + 22.5 if VDA > 337.51 then VDA = 0 FUEL = FUEL - 10 end sub
sub rotateLeft 'separate from Control so HAL can access VDA = VDA - 22.5 if VDA < -0.01 then VDA = VDA + 360 FUEL = FUEL - 10 end sub
sub HAL 'NEW, HAL is the Happy Auto-pilot Lander program 'HAL is allowed up to 1 command to control module for ajusting the trajectory 'first priority is get upright or nearly so thrusters
if AUTO = 1 then 'look for landing zone coming up 'this case handled first because most of time HAL is called in early if DX > 0 then for i = 1 to LZI '50 50 at .3, yDist = .3 * (LZY(i) - VY) if LZX(i) - VX < yDist and LZX(i) - VX > yDist -10 then 'straight 123 and 113 OK without yDist AUTO = 2 : TARGET = i : exit for end if next end if 'handle case DX < 0 'handle case DX = 0 end if
if AUTO = 2 then 'get DX speed down fast as possible and keep lem up high if DY > 0 and abs(DX) > .5 then 'thrust up and left or right if DX < .5 then 'get VDA to 135 before applying forward thrust if VDA >=0 and VDA < 135 then call rotateRight : exit sub if VDA >=315 and VDA < 360 then call rotateRight : exit sub if VDA > 135 and VDA < 315 then call rotateLeft : exit sub call forwardThrust : exit sub else if DX > .5 then 'get VDA to 45 before applying forward thrust if VDA >= 0 and VDA < 45 then call rotateRight : exit sub if VDA > 225 and VDA < 360 then call rotateRight : exit sub if VDA > 45 and VDA <= 225 then call rotateLeft : exit sub call forwardThrust : exit sub end if end if end if 'drop but not too fast if DY > 3.5 then if DX < -1 then if VDA < 90 then call rotateRight : exit sub call forwardThrust : exit sub end if if DX > 1 then if VDA > 90 then call rotateLeft : exit sub call forwardThrust : exit sub end if if VDA < 90 then call rotateRight : exit sub if VDA > 90 then call rotateLeft : exit sub call forwardThrust : exit sub end if end if 'auto = 2
end sub
sub makeSprites open "lem" for graphics as #makeSprites #makeSprites "down" #makeSprites "place 0 31 ; backColor black ; boxfilled 640 73" for x = 0 to 15 y = 1 call drawLEM x, y, 270 + x * 22.5, 2, "black" y = 2 call drawLEM x, y, 270 + x * 22.5, 2, "darkgray" call drawLEM x, y, 270 + x * 22.5, 1, "lightgray" call getSprite x next x close #makeSprites #lander "addsprite lem lem0 lem1 lem2 lem3 lem4 lem5 lem6 lem7 lem8 lem9 lem10 lem11 lem12 lem13 lem14 lem15" end sub
sub drawLEM xPosition, yPosition, uncorrectedAngle, penSize, color$ angle = uncorrectedAngle #makeSprites "north ; color "; color$; " ; up ; turn "; angle #makeSprites "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #makeSprites "size "; penSize #makeSprites "up ; go 4 ; down ; circlefilled 8" #makeSprites "turn 75 ; go 4 ; turn 180 ; go 4" #makeSprites "turn 30 ; go 4 ; turn 180 ; go 4 ; turn 255" #makeSprites "up ; turn 160 ; go 8" #makeSprites "down ; go 4 ; turn 110" #makeSprites "go 8 ; turn 110 ; go 4" #makeSprites "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #makeSprites "north ; up ; turn "; angle #makeSprites "go 4 ; turn 125 ; go 8 ; down ; turn 45 ; go 8" #makeSprites "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #makeSprites "north ; up ; turn "; angle #makeSprites "go 4 ; turn 235 ; go 8 ; down ; turn -45 ; go 8" end sub
sub setBackground #lander "down ; fill black" 'stars for s = 1 to 100 c=int(rnd(0)*100+156) #lander "color ";c;" ";c;" ";c #lander "size ";int(rnd(0)*4) #lander "set ";rnd(0)*800;" ";rnd(0)*600 next call drawTerrain #lander "getbmp stars 0 0 800 600" #lander "background stars" end sub
sub getSprite spritNum spriteX = spritNum * 30 #makeSprites "getbmp lem"; spritNum; " "; spriteX; " 1 30 60" end sub
sub drawTerrain rate1 = rnd(1) / (rnd(1) * 10 + 5) rate2 = rnd(1) / (rnd(1) * 5 + 5) #lander "down ; size 1 ; color white" for x = 0 to XMAX if rnd(1) < 0.015 then gosub [makeLandingZone] holder1 = holder1+rate1 holder2 = holder2+rate2 holder3 = holder3+sin(holder2)/20 y = 400+int(sin(holder1)*50)+int(cos(holder2)*50)+int(cos(holder3)*15) LANDH(x) = y c=rnd(0)*50+50 #lander "color ";c;" ";c;" ";c;" ; line ";x;" 600 ";x; " ";y next x exit sub
[makeLandingZone] width = int((rnd(1)*4+2)/2) for lz = x to min(799, x + 34 * width) LANDH(lz) = y c=rnd(0)*50+50 #lander "color ";c;" ";c;" ";c;" ; line ";lz;" 600 ";lz; " ";y next lz #lander "size 2" #lander "color yellow ; line ";x;" ";y;" ";lz;" ";y #lander "size 1" if LZI < 15 then 'new, save landing zone data for HAL "to see" LZI = LZI + 1 LZX(LZI) = x + int(.5 * width) : LZY(LZI) = y end if x = lz return end sub
sub label fColor$, bColor$, x, y, text$ #lander "color ";fColor$ #lander "backcolor ";bColor$ #lander "place ";x;" ";y #lander "boxfilled ";x + 8 * len(text$) + 10;" ";y + 20 #lander "place ";x + 5;" ";y + 15;";\";text$ end sub
|
|
|
Post by B+ on Nov 29, 2018 14:33:32 GMT
Since Christmas is coming, I thought I'd give you all a break by installing God mode, so if you are sure to crash you can press g and call God, you wont crash but you also wont get credit for a landing either. Alas MS Windows 10 has more power than God mode, and still will end a program and the JB,exe with the blue swirl at any time. It sure is not liking something about this program. Is there a way to check for memory leaks? Or can someone say if this is the way MS Windows 10 does handle a known memory leak? Will repost an updated HAL sub when I have Left and Right nudge worked out to control drifting towards target LZ (Landing Zone).
|
|
|
Post by carlgundel on Nov 29, 2018 23:11:50 GMT
Since Christmas is coming, I thought I'd give you all a break by installing God mode, so if you are sure to crash you can press g and call God, you wont crash but you also wont get credit for a landing either. Alas MS Windows 10 has more power than God mode, and still will end a program and the JB,exe with the blue swirl at any time. It sure is not liking something about this program. Is there a way to check for memory leaks? Or can someone say if this is the way MS Windows 10 does handle a known memory leak? Will repost an updated HAL sub when I have Left and Right nudge worked out to control drifting towards target LZ (Landing Zone). God mode = push a button and you're on the landing pad that instant?
|
|
|
Post by B+ on Nov 30, 2018 2:18:36 GMT
Hi Carl,
For God mode, I let the ship drop about 10 pixels over the closest landing area, more dramatic that way, I think.
In attempts to rid myself of the blue swirl circle and shutdown, I tried putting everything in one window, still shows up, dang!
Anyway, the nudging code is working pretty darn good now, here is progress update:
'Lander mod Auto mode.txt for JB v2 B+ post 2018-11-29 ' 2018-11-26 build from Lander mod 2.txt for JB v2 B+ 2018-05-29 ' which was built from: ' Lander by Carl mod Rod mod B+.bas for JB v2 started 2018-05-26 ' from Rod's mod of Lander.bas written by Carl Gundel ' carlg@world.std.com ' Needs at least Liberty BASIC v2.0 ???? ' This file is contributed to the public domain ' ' Development Notes: ' 2018-11-26 fix code and comment better, fix error /crash when lander beyond LANDH limits ' fix left arrow when VDA goes below 0 ' HAL code started with slow downs of DX and DY dropping and keeping upright ' 2018-11-27 Post report the crashing problem after a 2 - 21 rounds played. ' 2018-11-27 HAL now does Landing zone spotting and targeting now, pretty close! ' 2018-11-28 add God mod, press g so wont crash but wont get credit for Landing either ' 2018-11-29 simplfied drop code in AUTO = 2 section of HAL backed up again in God mod copy ' 2018-11-29 attempt to add nudge code ' 2018-11-29 found error in target x middle calculation, added yellow circle to spot VX + 15 and VY + 24 ' 2018-11-29 one window, new colors, fuel gage horizontal now. Almost pinpoint landings most times. ' ' ======================== INSTRUCTIONS ============================ ' ' Objective: You must make a VERY gentle and level landing on one of ' the flat areas with Lander in upright angle! ' ' Use the left or right arrow keys to rotate lander left or right ' Use the up arrow for forward Thrust ' NEW HERE! Use the "a" key to toggle auto pilot on and off ' '===================================================================
' globals all caps for easier code reading ' note: D stands for Delta the nerdy way to say change
' CONSTANTS global XMAX, YMAX, PI, D2R, DG XMAX = 800 'width drawing area needed YMAX = 600 'height of drawing area PI = acs(-1) 'constant pi D2R = PI / 180 'convert angle in degrees to radians DG = .1 'this is the constant change in vertical speed due to gravity
' GLOBAL VARIABLES for the subs dim LANDH(XMAX), LZX(15), LZY(15) 'array tracks y heights of land across the screen (x) global FUEL, SPEED, VDA, VX, VY, DX, DY 'for locating the Lander commented in [startGame] global LZI, AUTO, TARGET 'for toggle of Auto Pilot global LANDINGS, CRASHES
nomainwin WindowWidth = XMAX + 8 WindowHeight = YMAX + 32 UpperLeftX = int((DisplayWidth-WindowWidth)/2) UpperLeftY = int((DisplayHeight-WindowHeight)/2)
graphicbox #lander.fuel 150, YMAX - 60, 500, 20 open "Lunar Lander with Auto Pilot Toggle (key a)" for graphics_nsb as #lander #lander "trapclose quit" ' set end program code #lander "when characterInput control" ' set keypress code #lander "setfocus" ' catch keypresses see sub control
call makeSprites 'this sets up the lander image call startGame wait
sub startGame ' (re)initialize redraw and reset setting and game variables LZI = 0 ' track landing zone index call setBackground 'make landing scene and record surface heights of land in LANDH() #lander "spritexy lem 50 50" #lander.fuel "down ; fill red ; size 9 ; north ; turn 90 ; color darkgreen" FUEL = 500 ' this is the space vehicle's fuel SPEED = 6 ' this is the speed the vehicle is moving in the VDA direction VDA = 0 ' VDA is vehicle degree angle = orientation of the vehicle, 0 = pointed right due East VX = 50 ' this is current x position of vehicle 10 pixles from left side VY = 10 ' this is current y position of vehicle 10 pixels down from top of screen DX = SPEED * cos(D2R * VDA) ' this is the horizontal x change on screen due to speed and angle DY = SPEED * sin(D2R * VDA) ' this is the vertical y change on screen due to speed and angle
'new for HAL the auto pilot, AUTO will also track what stage HAL has advanced to between TIMER calls AUTO = 0 ' HAL the Auto Pilot sub will be toggled on /off with A or a keypress TARGET = 0 ' Target x aquired if <> 0 timer 100, timerTicked ' update Lander with the above variables end sub
sub quit H$ timer 0 close #lander end end sub
sub timerTicked 'This is the main display of simulation timer 0
if AUTO then call HAL ' is HAL landing the craft?
'vehicle falls faster and faster, because gravity effects the vertical speed DY = DY + DG 'speed up falling due to gravity acceleration
'new position = last postion plus the horizontal and vertical changes from momentum VX = VX + DX VY = VY + DY
if VX < 20 or VX > XMAX - 15 or VY < -100 then notice "You have drifted off screen." : call askGoAgain end if
if VY <= LANDH(VX + 15) - 24 and FUEL > 0 then #lander "discard" #lander "spriteimage lem lem"; int(VDA / 22.5) ' pull up the sprite angled closest to VDA #lander "spritexy lem "; VX; " "; VY ' locate on screen #lander "drawsprites" ' show background and lander #lander.fuel "cls ;fill red ;place 0 8 ; go ";FUEL ' show fuel usage #lander "color red" #lander "place ";VX + 15;" ";VY + 25;"; circlefilled ";2 #lander "color white" if TARGET then #lander "place ";LZX(TARGET);" ";LZY(TARGET);"; circle ";8 call label "white", "black", 5, 570, "HAL: ";AUTO;" LZ# ";TARGET call label "white", "black", 130, 570, "VDA: ";VDA call label "white", "black", 255, 570, "DX: ";int(DX*1000)/1000 call label "white", "black", 380, 570, "DY: ";int(DY*1000)/1000 call label "white", "black", XMAX - 300, 570, "LANDINGS: ";LANDINGS call label "white", "black", XMAX - 150, 570, "CRASHES: ";CRASHES timer 100, timerTicked ' restart timer else crash$ = "" if VDA <> 90 then crash$ = "Vehicle not upright. " if DY > 4 then crash$ = crash$ + "Came down too fast. " if DX > 4 then crash$ = crash$ + "Still moving hoizontally too fast. " if FUEL <= 0 then crash$ = crash$ + "Ran out of fuel. " if LANDH(VX + 7) <> LANDH(VX + 22) then crash$ = crash$ + "Did not land on level site. " if crash$ <> "" then cause$ = "You crashed!" + chr$(13) + crash$ CRASHES = CRASHES + 1 notice cause$ else LANDINGS = LANDINGS + 1 notice "Successful landing!"+ chr$(13) + "You lived to land again!" end if call askGoAgain end if #lander "flush" end sub
sub askGoAgain timer 0 confirm "Try again?"; answer if answer then call startGame else call quit "l" end sub
sub control H$, k$ key = asc(right$(k$, 1)) select case key case 65, 97 : if AUTO then AUTO = 0 else AUTO = 1 case 71, 103 : AUTO = 10 ' God mode case _VK_UP : call forwardThrust case _VK_LEFT : call rotateLeft case _VK_RIGHT : call rotateRight end select end sub
sub forwardThrust 'separate from Control so HAL can access thruster 'here is the vertical and horizontal change from a burst of fuel for thrust thrustx = 2 * cos(D2R * VDA + PI) thrusty = 2 * sin(D2R * VDA + PI) 'now change the horizontal and vertical momentums from the thrust DX = DX + thrustx DY = DY + thrusty 'update the position VX = VX + DX VY = VY + DY 'the thrust cost fuel FUEL = FUEL - 10 end sub
sub nudgeThrust 'separate from Control so HAL can access thruster 'here is the vertical and horizontal change from a burst of fuel for thrust thrustx = 1.5 * cos(D2R * VDA + PI) thrusty = 1.5 * sin(D2R * VDA + PI) 'now change the horizontal and vertical momentums from the thrust DX = DX + thrustx DY = DY + thrusty 'update the position VX = VX + DX VY = VY + DY 'the thrust cost fuel FUEL = FUEL - 5 end sub
sub rotateRight 'separate from Control so HAL can access VDA = VDA + 22.5 if VDA > 337.51 then VDA = 0 FUEL = FUEL - 10 end sub
sub rotateLeft 'separate from Control so HAL can access VDA = VDA - 22.5 if VDA < -0.01 then VDA = VDA + 360 FUEL = FUEL - 10 end sub
sub HAL 'NEW, HAL is the Happy Auto-pilot Lander program 'HAL is allowed up to 1 command to control module for ajusting the trajectory 'first priority is get upright or nearly so thrusters
if AUTO = 1 then 'look for landing zone coming up 'this case handled first because most of time HAL is called in early if DX > 0 then for i = 1 to LZI '50 50 at .3, yDist = .3 * (LZY(i) - VY) 'yDist and yDist - 10 works good but try a little later yet -5 and - 15 if LZX(i) - (VX + 15) < yDist + 5 and LZX(i) - (VX + 15) > yDist - 10 then 'straight 123 and 113 OK without yDist AUTO = 2 : TARGET = i : exit for end if next end if 'handle case DX < 0 'handle case DX = 0 end if
if AUTO = 2 then 'get DX speed down fast as possible and keep lem up high if DY > .2 and abs(DX) > .5 then 'thrust up and left or right if DX < .5 then 'get VDA to 135 before applying forward thrust if VDA >=0 and VDA < 135 then call rotateRight : exit sub if VDA >=315 and VDA < 360 then call rotateRight : exit sub if VDA > 135 and VDA < 315 then call rotateLeft : exit sub call forwardThrust : exit sub else if DX > .5 then 'get VDA to 45 before applying forward thrust if VDA >= 0 and VDA < 45 then call rotateRight : exit sub if VDA > 225 and VDA < 360 then call rotateRight : exit sub if VDA > 45 and VDA <= 225 then call rotateLeft : exit sub call forwardThrust : exit sub end if end if end if
'drop but not too fast if DY > 3.5 then if VDA < 90 then call rotateRight : exit sub if VDA > 90 then call rotateLeft : exit sub call forwardThrust : exit sub end if
'nudge code for drifting wrong way pdy = 4 * (LZY(TARGET) - (VY + 24) ) /LZY(TARGET)
' condition vehicle X is past target and drifting further past, hey don't nudge if too close vertically if (VX + 15) - LZX(TARGET) > pdy and DX >= 0 and VX > LZX(TARGET) and LZY(TARGET) - (VY + 24) > 4 then AUTO = 3 'for and thrust and then a rotate back call rotateLeft : exit sub end if
'condition vehicle x is before target and drifting further to left past if LZX(TARGET) - (VX + 15) > pdy and DX <= 0 and VX < LZX(TARGET) and LZY(TARGET) - (VY + 24) > 4 then AUTO = 5 call rotateRight : exit sub end if
'condition vehicle Y is close to target and drifting towards it but not fast enough
end if 'auto = 2
'after nudge Left if AUTO = 3 then AUTO = 4 call nudgeThrust : exit sub end if
if AUTO = 4 then AUTO = 2 'back to falling after rotation here call rotateRight : exit sub end if
'after nudge Right if AUTO = 5 then AUTO = 6 call nudgeThrust : exit sub end if
if AUTO = 6 and DY > 0 then AUTO = 2 'back to falling after rotation here call rotateLeft : exit sub end if
if AUTO = 10 then 'God mode VDA = 90 : DX = 0 : FUEL = 500 : DY = 1 ClosestBase = 100000 for i = 1 to LZI dist = sqr((VX - LZX(i))^2 + (VY - LZY(i))^2) if dist < ClosestBase then ClosestBase = dist : Base = i next VX = LZX(Base) + 9 : VY = LZY(Base) - 50 AUTO = 1 : LANDINGS = LANDINGS - 1 ' you get no credit for successful landing in God mode end if end sub
sub makeSprites 'open "lem" for graphics as #makeSprites #lander "down" '#lander "fill black" #lander "color black" #lander "place 0 31 ; backColor black ; boxfilled 640 73" 'call pause 2000 for x = 0 to 15 y = 1 call drawLEM x, y, 270 + x * 22.5, 2, "black" y = 2 call drawLEM x, y, 270 + x * 22.5, 2, "darkgray" call drawLEM x, y, 270 + x * 22.5, 1, "lightgray" call getSprite x 'call pause 2000 next x 'close #lander #lander "addsprite lem lem0 lem1 lem2 lem3 lem4 lem5 lem6 lem7 lem8 lem9 lem10 lem11 lem12 lem13 lem14 lem15" end sub
sub drawLEM xPosition, yPosition, uncorrectedAngle, penSize, color$ angle = uncorrectedAngle #lander "north ; color "; color$; " ; up ; turn "; angle #lander "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #lander "size "; penSize #lander "up ; go 4 ; down ; circlefilled 8" #lander "turn 75 ; go 4 ; turn 180 ; go 4" #lander "turn 30 ; go 4 ; turn 180 ; go 4 ; turn 255" #lander "up ; turn 160 ; go 8" #lander "down ; go 4 ; turn 110" #lander "go 8 ; turn 110 ; go 4" #lander "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #lander "north ; up ; turn "; angle #lander "go 4 ; turn 125 ; go 8 ; down ; turn 45 ; go 8" #lander "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #lander "north ; up ; turn "; angle #lander "go 4 ; turn 235 ; go 8 ; down ; turn -45 ; go 8" end sub
sub setBackground #lander "down ; fill black" 'stars for s = 1 to 100 c=int(rnd(0)*100+156) #lander "color ";c;" ";c;" ";c #lander "size ";int(rnd(0)*4) #lander "set ";rnd(0)*800;" ";rnd(0)*600 next call drawTerrain #lander "getbmp stars 0 0 800 600" #lander "background stars" end sub
sub getSprite spritNum spriteX = spritNum * 30 #lander "getbmp lem"; spritNum; " "; spriteX; " 1 30 60" end sub
sub drawTerrain rate1 = rnd(1) / (rnd(1) * 10 + 5) rate2 = rnd(1) / (rnd(1) * 5 + 5) #lander "down ; size 1 ; color white" for x = 0 to XMAX if rnd(1) < 0.015 and x > 5 then gosub [makeLandingZone] holder1 = holder1+rate1 holder2 = holder2+rate2 holder3 = holder3+sin(holder2)/20 y = 400+int(sin(holder1)*50)+int(cos(holder2)*50)+int(cos(holder3)*15) if x <= XMAX then LANDH(x) = y c=rnd(0)*50+50 #lander "color ";c;" ";c;" ";c;" ; line ";x;" 600 ";x; " ";y next x exit sub
[makeLandingZone] width = int((rnd(1)*4+2)/2) for lz = x to min(XMAX - 2, x + 34 * width) if lz <= XMAX then LANDH(lz) = y c=rnd(0)*50+50 #lander "color ";c;" ";c;" ";c;" ; line ";lz;" 600 ";lz; " ";y next lz #lander "size 2" #lander "color darkblue ; line ";x;" ";y;" ";lz;" ";y #lander "size 1" if LZI < 15 then 'new, save landing zone data for HAL "to see" LZI = LZI + 1 LZX(LZI) = x + int(.5 * width * 34) : LZY(LZI) = y end if x = lz return end sub
sub label fColor$, bColor$, x, y, text$ #lander "color ";fColor$ #lander "backcolor ";bColor$ #lander "place ";x;" ";y #lander "boxfilled ";x + 8 * len(text$) + 10;" ";y + 20 #lander "place ";x + 5;" ";y + 15;";\";text$ end sub
sub pause mil 'tsh version has scan built-in t0 = time$("ms") while time$("ms") < t0 + mil : scan : wend end sub
|
|
|
Post by Rod on Nov 30, 2018 9:40:42 GMT
I made some changes to the main loop. It was leaking memory, perhaps it is fixed now. Firstly I move the discard statement out of the conditional block and put it right at the start so it gets actioned every time. Secondly I set the timer off as soon as a crash was detected. Thirdly I removed the flush statement. Flush and Sprites don't mix. Usually line drawing and text printing don't mix well either but it seems ok here. Whether its fixed or not? Time will tell.
Flush was probably the culprit as each time through the loop you create a segment that never gets erased.
sub timerTicked 'This is the main display of simulation timer 0 #lander "discard"
if AUTO then call HAL ' is HAL landing the craft?
'vehicle falls faster and faster, because gravity effects the vertical speed DY = DY + DG 'speed up falling due to gravity acceleration
'new position = last postion plus the horizontal and vertical changes from momentum VX = VX + DX VY = VY + DY
if VX < 20 or VX > XMAX - 15 or VY < -100 then notice "You have drifted off screen." : call askGoAgain end if
if VY <= LANDH(VX + 15) - 24 and FUEL > 0 then
#lander "spriteimage lem lem"; int(VDA / 22.5) ' pull up the sprite angled closest to VDA #lander "spritexy lem "; VX; " "; VY ' locate on screen #lander "drawsprites" ' show background and lander #lander.fuel "cls ;fill red ;place 0 8 ; go ";FUEL ' show fuel usage #lander "color red" #lander "place ";VX + 15;" ";VY + 25;"; circlefilled ";2 #lander "color white" if TARGET then #lander "place ";LZX(TARGET);" ";LZY(TARGET);"; circle ";8 call label "white", "black", 5, 570, "HAL: ";AUTO;" LZ# ";TARGET call label "white", "black", 130, 570, "VDA: ";VDA call label "white", "black", 255, 570, "DX: ";int(DX*1000)/1000 call label "white", "black", 380, 570, "DY: ";int(DY*1000)/1000 call label "white", "black", XMAX - 300, 570, "LANDINGS: ";LANDINGS call label "white", "black", XMAX - 150, 570, "CRASHES: ";CRASHES timer 100, timerTicked ' restart timer else timer 0 crash$ = "" if VDA <> 90 then crash$ = "Vehicle not upright. " if DY > 4 then crash$ = crash$ + "Came down too fast. " if DX > 4 then crash$ = crash$ + "Still moving hoizontally too fast. " if FUEL <= 0 then crash$ = crash$ + "Ran out of fuel. " if LANDH(VX + 7) <> LANDH(VX + 22) then crash$ = crash$ + "Did not land on level site. " if crash$ <> "" then cause$ = "You crashed!" + chr$(13) + crash$ CRASHES = CRASHES + 1 notice cause$ else LANDINGS = LANDINGS + 1 notice "Successful landing!"+ chr$(13) + "You lived to land again!" end if call askGoAgain end if '#lander "flush" end sub
|
|
|
Post by B+ on Nov 30, 2018 13:53:59 GMT
Hi Rod,
Thanks for confirming my suspicions. I look forward to trying out your changes. I have a couple more ideas up my sleeve but yours are the least disruptive.
Update: still persists, time to try my sleeve.
|
|
|
Post by Rod on Nov 30, 2018 17:46:23 GMT
I am off on a different track. I have always thought that Lander lacked feedback on the physics. As a game when run at the correct speed the physics were good. The lander had mass and the thrust had to be juggled to achieve what you wanted but what was missing was visual thrust feedback. So that's where I am headed. I also adopted a Marshian theme since we have just achieved a real landing there. Once I get the thrust feedback done I will think about HAL but for me that just spoils the game.
'Lander.bas 'written by Carl Gundel 'carlg@world.std.com 'Needs at least Liberty BASIC v2.0 'This file is contributed to the public domain
'Use the left or right arrow keys to rotate left or right 'Use the up or down arrow to increase or decrease thrust
'You must make a VERY gentle and level landing 'on one of the flat areas!
'open game window
nomainwin WindowWidth = 800 WindowHeight = 600 UpperLeftX = int((DisplayWidth-WindowWidth)/2) UpperLeftY = int((DisplayHeight-WindowHeight)/2) dim terrain(WindowWidth) graphicbox #lander.fuel 10,10,10,500 open "Lunar Lander" for graphics_nsb as #lander #lander "when characterInput [control]" #lander "trapclose [quit]"
call makeSprites 'call setBackground #lander "spritexy lem 50 50" #lander.fuel "down ; fill yellow ; size 4 ; north ;color green"
[startGame] 'initialize call setBackground #lander "setfocus" fuel = 250 altitude = 0 attitude = 0 longitude = 10 thrust = 0 call setHorizSpeed 8 call setVertSpeed 0 call gravityAccelerate timer 100, [timerTicked] startTime = time$("milliseconds") wait
[timerTicked] 'This is the main simulation routine!
frames = frames + 1 if altitude <= terrain(longitude+15) - 24 and fuel>0 then fuel=fuel-thrust call setAttitude attitude call applyThrust thrust, attitude call gravityAccelerate altitude = altitude + getVertSpeed() longitude = max(0, min(785, longitude + getHorizSpeed())) #lander "spritexy lem "; longitude; " "; altitude #lander "drawsprites" #lander.fuel "cls ;fill yellow ;color red ;place 4 500 ; go ";fuel*2 else timer 0 crash = landerCrashed(longitude, attitude,fuel) if crash then cause$="You crashed!"+chr$(13) if crash and 1 then cause$=cause$+"Not verticle"+chr$(13) if crash and 2 or crash and 4 then cause$=cause$+"Too fast"+chr$(13) if crash and 8 then cause$=cause$+"Missed the base"+chr$(13) if crash and 16 then cause$=cause$+"Out of fuel" notice cause$ else notice "Successful landing!" end if confirm "Try again?"; answer if answer then [startGame] else [quit] end if
wait
[quit] timer 0 close #lander
end
[control] key = asc(right$(Inkey$,1)) select case key case _VK_UP thrustInput=thrustInput+(thrustInput<9) if thrustInput then thrust = (thrustInput - 1) / 8 * 0.55 + 0.333
case _VK_DOWN thrustInput=thrustInput-(thrustInput>0) if thrustInput then thrust = (thrustInput - 1) / 8 * 0.55 + 0.333
case _VK_LEFT attitude = attitude - 22.5 if attitude < -0.01 then attitude = 337.5
case _VK_RIGHT attitude = attitude + 22.5 if attitude > 337.51 then attitude = 0 end select wait
function landerCrashed(xPosition, attitude,fuel)
if attitude<89 or attitude>91 then landerCrashed=landerCrashed+1 if getVertSpeed() > 4 then landerCrashed=landerCrashed+2 if getHorizSpeed() > 4 then landerCrashed=landerCrashed+4 if terrain(xPosition+7) <> terrain(xPosition+22) then landerCrashed=landerCrashed+8 if fuel<=0 then landerCrashed=landerCrashed+16 end function
sub makeSprites
open "lem" for graphics as #makeSprites #makeSprites "down" #makeSprites "place 0 31 ; backColor black ; boxfilled 640 73" for x = 0 to 15 y = 1 call drawLEM x, y, 270 + x * 22.5, 1, "black","black" y = 2 call drawLEM x, y, 270 + x * 22.5, 1, "yellow","brown" call getSprite x next x close #makeSprites #lander "addsprite lem lem0 lem1 lem2 lem3 lem4 lem5 lem6 lem7 lem8 lem9 lem10 lem11 lem12 lem13 lem14 lem15"
end sub
sub drawLEM xPosition, yPosition, uncorrectedAngle, penSize, color$ ,bcolor$ angle = uncorrectedAngle #makeSprites "north ; color "; color$; " ; backcolor ";bcolor$;" ; up ; turn "; angle #makeSprites "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #makeSprites "size "; penSize #makeSprites "up ; go 4 ; down ; circlefilled 8" #makeSprites "turn 75 ; go 4 ; turn 180 ; go 4" #makeSprites "turn 30 ; go 4 ; turn 180 ; go 4 ; turn 255" #makeSprites "up ; turn 160 ; go 8" #makeSprites "down ; go 4 ; turn 110" #makeSprites "go 8 ; turn 110 ; go 4" #makeSprites "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #makeSprites "north ; up ; turn "; angle #makeSprites "go 4 ; turn 125 ; go 8 ; down ; turn 45 ; go 8" #makeSprites "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #makeSprites "north ; up ; turn "; angle #makeSprites "go 4 ; turn 235 ; go 8 ; down ; turn -45 ; go 8"
end sub
sub setBackground #lander "down ; fill darkblue" 'stars for s = 1 to 100 c=int(rnd(0)*100+156) #lander "color ";c;" ";c;" ";c #lander "size ";int(rnd(0)*4) #lander "set ";rnd(0)*800;" ";rnd(0)*600 next call drawTerrain #lander "getbmp stars 0 0 800 600" #lander "background stars"
end sub
sub getSprite spritNum spriteX = spritNum * 30 #makeSprites "getbmp lem"; spritNum; " "; spriteX; " 1 30 60" end sub
sub setHorizSpeed xSpeed vars(0) = xSpeed end sub
sub setVertSpeed ySpeed vars(1) = ySpeed end sub
function getHorizSpeed() getHorizSpeed = vars(0) end function
function getVertSpeed() getVertSpeed = vars(1) end function
sub setAttitude degrees #lander "spriteimage lem lem"; int(degrees / 22.5) end sub
sub gravityAccelerate call setVertSpeed getVertSpeed() + 0.3'(6/18) end sub
sub applyThrust qtyFuel, angle angleXform = angle / 180 * 3.141592 call setHorizSpeed getHorizSpeed() - (qtyFuel/2) * cos(angleXform) call setVertSpeed getVertSpeed() - (qtyFuel/2) * sin(angleXform) end sub
sub drawTerrain c=50 for y=200 to 600 step 20 #lander "size 1 ; color ";c;" ";c/2;" ";10 y1=y+rnd(0)*2+.5 -2 for x=1 to 799 #lander "line ";x;" 600 ";x;" ";y1 y1=y1+rnd(0)*3+.5 -2 terrain(x)=600 next c=c+10 next #lander "color yellow" lx=rnd(0)*600+100 ly=rnd(0)*200+300 for n= 1 to 360 x=lx-(20*sin(n/57.29577951)) y=ly-(5*cos(n/57.29577951)) print #lander, "set ";x;" ";y terrain(x)=ly next end sub
|
|
|
Post by Rod on Nov 30, 2018 18:26:09 GMT
Back to the problem code. Try this. I encase the timer in its own Sub and it never runs outside that so cannot sidetrack the program if a timer event fires when we are elsewhere. I have removed all timer 0 lines. Now the only outstanding event is the when keyboardInput There might have been a conflict between these two events. But again only time will tell. If it still crashes turn of the when keyboardInput at the start of the timer routine and back on when it ends.
'Lander mod Auto mode.txt for JB v2 B+ started 2018-11-26 post 2018-11-28 ' 2018-11-26 build from Lander mod 2.txt for JB v2 B+ 2018-05-29 ' which was built from: ' Lander by Carl mod Rod mod B+.bas for JB v2 started 2018-05-26 ' from Rod's mod of Lander.bas written by Carl Gundel ' carlg@world.std.com ' Needs at least Liberty BASIC v2.0 ???? ' This file is contributed to the public domain ' ' Development Notes: ' 2018-11-26 fix code and comment better, fix error /crash when lander beyond LANDH limits ' fix left arrow when VDA goes below 0 ' HAL code started with slow downs of DX and DY dropping and keeping upright ' 2018-11-27 Post, report the crashing problem after a 2 - 21 rounds played. ' 2018-11-28 Post, HAL now does Landing zone spotting and targeting now, pretty close! ' ' ======================== INSTRUCTIONS ============================ ' ' Objective: You must make a VERY gentle and level landing on one of ' the flat areas with Lander in upright angle! ' ' Use the left or right arrow keys to rotate lander left or right ' Use the up arrow for forward Thrust ' NEW HERE! Use the "a" key to toggle auto pilot on and off ' '===================================================================
' globals all caps for easier code reading ' note: D stands for Delta the nerdy way to say change
' CONSTANTS global XMAX, YMAX, PI, D2R, DG, DAT XMAX = 800 'width drawing area needed YMAX = 600 'height of drawing area PI = acs(-1) 'constant pi D2R = PI / 180 'convert angle in degrees to radians DG = .1 'this is the constant change in vertical speed due to gravity DAT = 2 'this is constant change of Acceleration when thrust has been applied
' GLOBAL VARIABLES for the subs dim LANDH(XMAX), LZX(15), LZY(15) 'array tracks y heights of land across the screen (x) global FUEL, SPEED, VDA, VX, VY, DX, DY 'for locating the Lander commented in [startGame] global LZI, AUTO, TARGET 'for toggle of Auto Pilot global LANDINGS, CRASHES
nomainwin WindowWidth = XMAX + 8 WindowHeight = YMAX + 32 UpperLeftX = int((DisplayWidth-WindowWidth)/2) UpperLeftY = int((DisplayHeight-WindowHeight)/2)
graphicbox #lander.fuel 10,10,10,500 open "Lunar Lander with Auto Pilot Toggle (key a)" for graphics_nsb as #lander #lander "trapclose quit" ' set end program code #lander "when characterInput control" ' set keypress code #lander "setfocus" ' catch keypresses see sub control
call makeSprites 'this sets up the lander image call startGame wait
sub startGame ' (re)initialize redraw and reset setting and game variables LZI = 0 ' track landing zone index call setBackground 'make landing scene and record surface heights of land in LANDH() #lander "spritexy lem 50 50" #lander.fuel "down ; fill red ; size 4 ; north ;color yellow" FUEL = 500 ' this is the space vehicle's fuel SPEED = 6 ' this is the speed the vehicle is moving in the VDA direction VDA = 0 ' VDA is vehicle degree angle = orientation of the vehicle, 0 = pointed right due East VX = 50 ' this is current x position of vehicle 10 pixles from left side VY = 10 ' this is current y position of vehicle 10 pixels down from top of screen DX = SPEED * cos(D2R * VDA) ' this is the horizontal x change on screen due to speed and angle DY = SPEED * sin(D2R * VDA) ' this is the vertical y change on screen due to speed and angle
'new for HAL the auto pilot, AUTO will also track what stage HAL has advanced to between TIMER calls AUTO = 0 ' HAL the Auto Pilot sub will be toggled on /off with A or a keypress TARGET = 0 ' Target x aquired if <> 0 while 1 call gameloop wend end sub
sub quit H$ close #lander end end sub
sub gameloop 'This is the main display of simulation call pause 100
if AUTO then call HAL ' is HAL landing the craft?
'vehicle falls faster and faster, because gravity effects the vertical speed DY = DY + DG 'speed up falling due to gravity acceleration
'new position = last postion plus the horizontal and vertical changes from momentum VX = VX + DX VY = VY + DY
if VX < 20 or VX > XMAX - 15 or VY < -100 then notice "You have drifted off screen." : call askGoAgain end if
if VY <= LANDH(VX + 15) - 24 and FUEL > 0 then #lander "discard" #lander "spriteimage lem lem"; int(VDA / 22.5) ' pull up the sprite angled closest to VDA #lander "spritexy lem "; VX; " "; VY ' locate on screen #lander "drawsprites" ' show background and lander #lander.fuel "cls ;fill red ;place 4 500 ; go ";FUEL ' show fuel usage call label "white", "black", 5, 570, "HAL: ";AUTO;" LZ# ";TARGET call label "white", "black", 130, 570, "VDA: ";VDA call label "white", "black", 255, 570, "DX: ";int(DX*1000)/1000 call label "white", "black", 380, 570, "DY: ";int(DY*1000)/1000 call label "white", "black", XMAX - 300, 570, "LANDINGS: ";LANDINGS call label "white", "black", XMAX - 150, 570, "CRASHES: ";CRASHES else crash$ = "" if VDA <> 90 then crash$ = "Vehicle not upright. " if DY > 4 then crash$ = crash$ + "Came down too fast. " if DX > 4 then crash$ = crash$ + "Still moving hoizontally too fast. " if FUEL <= 0 then crash$ = crash$ + "Ran out of fuel. " if LANDH(VX + 7) <> LANDH(VX + 22) then crash$ = crash$ + "Did not land on level site. " if crash$ <> "" then cause$ = "You crashed!" + chr$(13) + crash$ CRASHES = CRASHES + 1 notice cause$ else LANDINGS = LANDINGS + 1 notice "Successful landing!"+ chr$(13) + "You lived to land again!" end if call askGoAgain end if end sub
sub pause ms timer , ms ,[done] wait [done] timer 0 end sub
sub askGoAgain confirm "Try again?"; answer if answer then call startGame else call quit "l" end sub
sub control H$, k$ key = asc(right$(k$, 1)) select case key case 65, 97 : if AUTO then AUTO = 0 else AUTO = 1 case _VK_UP : call forwardThrust case _VK_LEFT : call rotateLeft case _VK_RIGHT : call rotateRight end select end sub
sub forwardThrust 'separate from Control so HAL can access thruster 'here is the vertical and horizontal change from a burst of fuel for thrust thrustx = DAT * cos(D2R * VDA + PI) thrusty = DAT * sin(D2R * VDA + PI) 'now change the horizontal and vertical momentums from the thrust DX = DX + thrustx DY = DY + thrusty 'update the position VX = VX + DX VY = VY + DY 'the thrust cost fuel FUEL = FUEL - 10 end sub
sub rotateRight 'separate from Control so HAL can access VDA = VDA + 22.5 if VDA > 337.51 then VDA = 0 FUEL = FUEL - 10 end sub
sub rotateLeft 'separate from Control so HAL can access VDA = VDA - 22.5 if VDA < -0.01 then VDA = VDA + 360 FUEL = FUEL - 10 end sub
sub HAL 'NEW, HAL is the Happy Auto-pilot Lander program 'HAL is allowed up to 1 command to control module for ajusting the trajectory 'first priority is get upright or nearly so thrusters
if AUTO = 1 then 'look for landing zone coming up 'this case handled first because most of time HAL is called in early if DX > 0 then for i = 1 to LZI '50 50 at .3, yDist = .3 * (LZY(i) - VY) if LZX(i) - VX < yDist and LZX(i) - VX > yDist -10 then 'straight 123 and 113 OK without yDist AUTO = 2 : TARGET = i : exit for end if next end if 'handle case DX < 0 'handle case DX = 0 end if
if AUTO = 2 then 'get DX speed down fast as possible and keep lem up high if DY > 0 and abs(DX) > .5 then 'thrust up and left or right if DX < .5 then 'get VDA to 135 before applying forward thrust if VDA >=0 and VDA < 135 then call rotateRight : exit sub if VDA >=315 and VDA < 360 then call rotateRight : exit sub if VDA > 135 and VDA < 315 then call rotateLeft : exit sub call forwardThrust : exit sub else if DX > .5 then 'get VDA to 45 before applying forward thrust if VDA >= 0 and VDA < 45 then call rotateRight : exit sub if VDA > 225 and VDA < 360 then call rotateRight : exit sub if VDA > 45 and VDA <= 225 then call rotateLeft : exit sub call forwardThrust : exit sub end if end if end if 'drop but not too fast if DY > 3.5 then if DX < -1 then if VDA < 90 then call rotateRight : exit sub call forwardThrust : exit sub end if if DX > 1 then if VDA > 90 then call rotateLeft : exit sub call forwardThrust : exit sub end if if VDA < 90 then call rotateRight : exit sub if VDA > 90 then call rotateLeft : exit sub call forwardThrust : exit sub end if end if 'auto = 2
end sub
sub makeSprites open "lem" for graphics as #makeSprites #makeSprites "down" #makeSprites "place 0 31 ; backColor black ; boxfilled 640 73" for x = 0 to 15 y = 1 call drawLEM x, y, 270 + x * 22.5, 2, "black" y = 2 call drawLEM x, y, 270 + x * 22.5, 2, "darkgray" call drawLEM x, y, 270 + x * 22.5, 1, "lightgray" call getSprite x next x close #makeSprites #lander "addsprite lem lem0 lem1 lem2 lem3 lem4 lem5 lem6 lem7 lem8 lem9 lem10 lem11 lem12 lem13 lem14 lem15" end sub
sub drawLEM xPosition, yPosition, uncorrectedAngle, penSize, color$ angle = uncorrectedAngle #makeSprites "north ; color "; color$; " ; up ; turn "; angle #makeSprites "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #makeSprites "size "; penSize #makeSprites "up ; go 4 ; down ; circlefilled 8" #makeSprites "turn 75 ; go 4 ; turn 180 ; go 4" #makeSprites "turn 30 ; go 4 ; turn 180 ; go 4 ; turn 255" #makeSprites "up ; turn 160 ; go 8" #makeSprites "down ; go 4 ; turn 110" #makeSprites "go 8 ; turn 110 ; go 4" #makeSprites "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #makeSprites "north ; up ; turn "; angle #makeSprites "go 4 ; turn 125 ; go 8 ; down ; turn 45 ; go 8" #makeSprites "place "; (xPosition)*30+15; " "; (yPosition-1)*30+15 #makeSprites "north ; up ; turn "; angle #makeSprites "go 4 ; turn 235 ; go 8 ; down ; turn -45 ; go 8" end sub
sub setBackground #lander "down ; fill black" 'stars for s = 1 to 100 c=int(rnd(0)*100+156) #lander "color ";c;" ";c;" ";c #lander "size ";int(rnd(0)*4) #lander "set ";rnd(0)*800;" ";rnd(0)*600 next call drawTerrain #lander "getbmp stars 0 0 800 600" #lander "background stars" end sub
sub getSprite spritNum spriteX = spritNum * 30 #makeSprites "getbmp lem"; spritNum; " "; spriteX; " 1 30 60" end sub
sub drawTerrain rate1 = rnd(1) / (rnd(1) * 10 + 5) rate2 = rnd(1) / (rnd(1) * 5 + 5) #lander "down ; size 1 ; color white" for x = 0 to XMAX if rnd(1) < 0.015 then gosub [makeLandingZone] holder1 = holder1+rate1 holder2 = holder2+rate2 holder3 = holder3+sin(holder2)/20 y = 400+int(sin(holder1)*50)+int(cos(holder2)*50)+int(cos(holder3)*15) LANDH(x) = y c=rnd(0)*50+50 #lander "color ";c;" ";c;" ";c;" ; line ";x;" 600 ";x; " ";y next x exit sub
[makeLandingZone] width = int((rnd(1)*4+2)/2) for lz = x to min(799, x + 34 * width) LANDH(lz) = y c=rnd(0)*50+50 #lander "color ";c;" ";c;" ";c;" ; line ";lz;" 600 ";lz; " ";y next lz #lander "size 2" #lander "color yellow ; line ";x;" ";y;" ";lz;" ";y #lander "size 1" if LZI < 15 then 'new, save landing zone data for HAL "to see" LZI = LZI + 1 LZX(LZI) = x + int(.5 * width) : LZY(LZI) = y end if x = lz return end sub
sub label fColor$, bColor$, x, y, text$ #lander "color ";fColor$ #lander "backcolor ";bColor$ #lander "place ";x;" ";y #lander "boxfilled ";x + 8 * len(text$) + 10;" ";y + 20 #lander "place ";x + 5;" ";y + 15;";\";text$ end sub
|
|