Author Topic: b+ Asteroids makeover  (Read 19768 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #60 on: November 04, 2020, 11:21:21 am »
Update: I did review Asteroids videos and I found someone with restored Atari 1979 or 80's Arcade Game and he went over the entire machine including trivia on coin boxes and outer detailing. Importantly he showed controls and instructions for them off original machine.

No reverse thrusters nor stop, there are 5 buttons. For left hand, two gun spinners left and right located as you would expect. 2 buttons for the right hand, thrust and fire (left to right) and in the middle and lower is Hyperspace jumper for better or worse position, to be used when crash is imminent.

Oh and a cool effect with thruster, it sets ship in motion of where the gun is pointing and drifts that way for awhile but eventually slows to stop unless more pumping of thruster meanwhile while moving/drifting you can spin your gun/ship in any direction to shoot. Which reminds me of action/adventure movies when the hero is sliding across floor or down a zip line with guns blazing in both directions taking out all the baddies.

Anyway, tried to duplicate that set of controls in the Thruster tester code, OK.
Keys A, S are left and right spinners, K =thrust, L =Fire thrust reads direction of guns at moment and sends ship that way for about 100+ pixels coming to stop unless thruster is pumped (then you basically start going out one border and in the opposite side so fast you don't have time to aim at anything.) Spacebar = Hyperspace jump (down from left and right hand buttons/keys and in middle just like controls on arcade machine.

I had difficulties one after the other when installing this set of controls into m8 for version m9 with rocks, aliens and live bullets... getting the guns to spin the right speed fast but also pinpoint shoot. Hit the thruster twice and you are crashed into border rock waiting to be released to screen. And Hyperspace only worked once or twice for some unknown reason I haven't figured out yet.

There is a question of pumping the key or laying on the key for spinning and firing. If you want to lay on the key then you need _KEYDOWN that can do several keys at once. If you want to pump keys for limited burst you need inkey or _KEYHIT...  anyway the Hyperspace problem had me baffled why I couldn't jump again and again if I wanted. I could jump once per life and maybe if waited long enough (for what?) jump again didn't matter if _KEYHIT, INKEY$ or _KEYDOWN it would only jump once. ??? a head scratcher!
« Last Edit: November 04, 2020, 11:28:44 am by bplus »

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: b+ Asteroids makeover
« Reply #61 on: November 04, 2020, 12:24:40 pm »
B+, let's see the code, maybe I can find the problem. If it's not a flow problem, then it could be a variable that doesn't change how you need it to. I've noticed in the past that sometimes inkey$ will hold onto its past string amount, which is why I often say a$ = "" after it doesn't need it anymore.
« Last Edit: November 04, 2020, 12:25:56 pm by SierraKen »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #62 on: November 04, 2020, 01:34:32 pm »
Here I've fixed up thrust code for k key, everything is working just right here, now, since last post.

You can pump thrust k key while spin and fire all at once. I think this duplicates the cool effect Asteroids has.

Code: QB64: [Select]
  1. _TITLE "Astroids a s spacebarn k l controls" 'b+ 2020-11-04
  2. CONST xmax = 1024, ymax = 700, pi = _PI
  3. SCREEN _NEWIMAGE(xmax, ymax, 32)
  4. _SCREENMOVE 100, 10
  5.  
  6. ' a turn left
  7. ' s turn right
  8. ' spacebarn  "hyperspace" worm hole  bug out and show up somewhere else
  9. ' k thrust  just a burst in direction you are pointed
  10. ' l fire! owwha, owha, owha...
  11.  
  12.  
  13. TYPE shipType
  14.     x AS SINGLE
  15.     y AS SINGLE
  16.     live AS LONG
  17.     speed AS SINGLE
  18.     thrustAngle AS SINGLE
  19.     angle AS SINGLE '   rotated position usu gun left or right (mouse button), maybe up press w or down press z
  20.     thrust AS LONG ' use thruster as a count down, reset at each thrust change
  21.  
  22. DIM SHARED ship AS shipType
  23. ship.x = xmax / 2: ship.y = ymax / 2: ship.angle = 0: ship.speed = 3.5
  24. WHILE _KEYDOWN(27) = 0
  25.     CLS
  26.     PRINT ship.thrust
  27.  
  28.     ' Instruments Panel
  29.  
  30.     'a left spin
  31.     IF _KEYDOWN(97) THEN ship.angle = ship.angle - pi / 48
  32.  
  33.     's right spin
  34.     IF _KEYDOWN(115) THEN ship.angle = ship.angle + pi / 48
  35.  
  36.     'l is Fire!
  37.     IF _KEYDOWN(108) THEN
  38.         t = TIMER(.001)
  39.         IF lastt = 0 OR t - lastt < .1 THEN fire = 1: SOUND 4088, .1
  40.     END IF
  41.     kh& = _KEYHIT
  42.     SELECT CASE kh&
  43.         CASE 107 'thrust  k key
  44.             ship.thrustAngle = ship.angle: ship.thrust = 120
  45.         CASE 32 ' space = hyperspace jump
  46.             ship.x = (xmax - 200) * RND + 100: ship.y = (ymax - 200) * RND + 100: ship.thrust = 0
  47.     END SELECT
  48.  
  49.     drawship
  50.     _DISPLAY
  51.     _LIMIT 60 ' same as Asteroids Game
  52.  
  53. SUB drawship 'simple red iso triangle pointed towards radianAngle
  54.     DIM x1 AS LONG, y1 AS LONG, x2 AS LONG, y2 AS LONG, x3 AS LONG, y3 AS LONG
  55.     DIM x4 AS LONG, y4 AS LONG, x5 AS LONG, y5 AS LONG
  56.     IF ship.thrust > 0 THEN
  57.         'relocate ship position
  58.         ship.x = ship.x + ship.speed * COS(ship.thrustAngle)
  59.         ship.y = ship.y + ship.speed * SIN(ship.thrustAngle)
  60.         'jump borders
  61.         IF ship.x < 0 THEN ship.x = xmax - ABS(ship.x)
  62.         IF ship.x > xmax THEN ship.x = ship.x - xmax
  63.         IF ship.y < 0 THEN ship.y = ymax - ABS(ship.y)
  64.         IF ship.y > ymax THEN ship.y = ship.y - ymax
  65.         'burn out flame as thruster dies out
  66.         x4 = ship.x + .5 * ship.thrust * COS(ship.angle - 17 / 18 * pi)
  67.         y4 = ship.y + .5 * ship.thrust * SIN(ship.angle - 17 / 18 * pi)
  68.         x5 = ship.x + .5 * ship.thrust * COS(ship.angle - 19 / 18 * pi)
  69.         y5 = ship.y + .5 * ship.thrust * SIN(ship.angle - 19 / 18 * pi)
  70.         ftri ship.x, ship.y, x4, y4, x5, y5, &H99FFFF88
  71.         ship.thrust = ship.thrust - 1
  72.     END IF
  73.     'draw ship dead or alive thrust or not, calculate 3 points of triangle ship
  74.     fcirc ship.x, ship.y, 30, &H05FFFFFF
  75.     x1 = ship.x + 30 * COS(ship.angle) ' front point
  76.     y1 = ship.y + 30 * SIN(ship.angle) '
  77.     x2 = ship.x + 30 * COS(ship.angle + .6666 * pi) ' wing
  78.     y2 = ship.y + 30 * SIN(ship.angle + .6666 * pi)
  79.     x3 = ship.x + 30 * COS(ship.angle - .6666 * pi) ' other wing
  80.     y3 = ship.y + 30 * SIN(ship.angle - .6666 * pi)
  81.     ftri ship.x, ship.y, x1, y1, x2, y2, _RGB32(80, 120, 80, 80)
  82.     ftri ship.x, ship.y, x1, y1, x3, y3, _RGB32(60, 100, 60, 80)
  83.     LINE (x1, y1)-(ship.x, ship.y), _RGB32(255, 255, 128)
  84.     LINE (x1, y1)-(x2, y2), _RGB32(255, 180, 40)
  85.     LINE (x1, y1)-(x3, y3), _RGB32(255, 180, 40)
  86.  
  87. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  88.     DIM D AS LONG
  89.     STATIC a&
  90.     D = _DEST
  91.     IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32)
  92.     _DEST a&
  93.     _DONTBLEND a& '  '<<<< new 2019-12-16 fix
  94.     PSET (0, 0), K
  95.     _BLEND a& '<<<< new 2019-12-16 fix
  96.     _DEST D
  97.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  98.  
  99. SUB fcirc (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG) 'vince version
  100.     DIM x0 AS LONG, y0 AS LONG, e AS LONG
  101.     x0 = R: y0 = 0: e = 0
  102.     DO WHILE y0 < x0
  103.         IF e <= 0 THEN
  104.             y0 = y0 + 1
  105.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  106.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  107.             e = e + 2 * y0
  108.         ELSE
  109.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  110.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  111.             x0 = x0 - 1: e = e - 2 * x0
  112.         END IF
  113.     LOOP
  114.     LINE (x - R, y)-(x + R, y), C, BF
  115.  
  116.  


Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #63 on: November 04, 2020, 01:42:44 pm »
@SierraKen

Here is defective Hyperspace jump, I'm afraid I've messed up the code worse trying different things ie slowed way down?
But here is state of affairs as of quitting in frustration last night:

Code: QB64: [Select]
  1. _TITLE "b+ Asteroids m9 AS-Space-KL " 'started 2018-07-13"
  2.  
  3. '                                            New Controls
  4. ' key a = turn left
  5. ' key s = turn right
  6. '          spacebar =  "hyperspace" show up somewhere else  better or worse use when collision is imminent
  7. ' key k = thrust  just a burst in direction you are pointed but doesn't last
  8. ' key l = fire! owwha, owha, owha...
  9.  
  10. '=================================================================================================================
  11.  
  12. ' 2020-10-27 remove the alternate subs and get down below 200 LOC almost there now! new shooter action font and background
  13. ' 2020-10-28 another makeover explosions and split asteroids
  14. ' 2020-10-29 fix baby rock management, break between lives
  15. ' 2020-10-29 fix left/right gun, fix explosions over many frames to eliminate pause in action, speed up 60 fps
  16. ' 2020-10-30 m3 SierraKen's idea to angle shooter with mousewheel also finish WASD options, more rocks, points system
  17. ' points:
  18. ' The higher the speed the better    speed range .5 to 2.5, diff = 2 * 50 = 100          s - .5 * 50
  19. ' DELETE The lower the color the better   color range 10 to 60, diff =      50 * 2 = 100  50 - (c - 10) * 2
  20. ' The smaller the size the better  size range 10 to 100, diff = 90 * 1.1111 = 100  90 - (sz -10) * 1.1111
  21. '        ((speed - .5) * 50 + (90 - (r - 10)) * 1.1111) / 2 = 100 best score per hit
  22. ' 2020-10-30 increase level of difficulty, fix double lives lost, add an ending after all lives spent.
  23. ' 2020-10-31 M4 They are Here - the aliens have accepted my invitaion for war games don't get caught in their beam.
  24. ' rework ending and variable LONG suffix. Aliens on the attack 100 points before or after transformed into the Bolder of Death.
  25. ' 2020-11-01 M5 FX Moving through space, Oh yeah, more aliens!
  26. ' 2020-11-01 M6 add play again and save high game , continuous shoot
  27. ' 2020-11-01 M7 fix hits count when hit alien ship or Bolder of Death. Fix lights on aliens ship. I want to see collsions with ship.
  28. ' Ken recommends removing text in middle of screen, yeah, distracting. Makeover ship as with mouse x, y it's center. Add Splash screen.
  29. ' Show mouse in between lives so can be in screen center when press key to start next run.
  30.  
  31. ' 2020-11-03 watching videos on Asteroids, I found a view and description of the control panel, it is:
  32. ' 2 buttons on left and lower button in middle and 2 buttons on right level with 2 on left
  33. ' 2 buttons on left are left and right turns they will be Keys A and S
  34. ' the middle will be spacebar for Hypespace or these days we might call it worm hole, jump to another location better or worse!
  35. ' 2 buttons on right K and L: K will be a thruster of sorts you evetually come to a stop L is the fire button
  36. ' So let's try that. I am impressed by hitting thruster and shooting all around as you dift in direction gun was pionted when hit thruster.
  37. ' Lighten rocks change points without rock color
  38.  
  39. '================================================================================================================
  40.  
  41. '    NOTE: !!!!!!!!!!!!!!!   When there is a pause in action, just hit = enter,  as in enter a new life!
  42.  
  43. '================================================================================================================
  44.  
  45. CONST xmax = 1200, ymax = 700, pi = _PI, polyAngle = _PI / 6, nRocks = 300, nBullets = 2000, bSpeed = 15
  46.  
  47. TYPE alienType
  48.     x AS SINGLE
  49.     y AS SINGLE
  50.     dx AS SINGLE
  51.     dy AS SINGLE
  52.     ls AS LONG ' lights offset
  53.     c AS _UNSIGNED LONG ' color
  54.     live AS LONG
  55.     attackFrame AS LONG
  56.     fireX AS SINGLE
  57.     fireY AS SINGLE
  58.     transform AS LONG
  59.  
  60. TYPE particle
  61.     x AS SINGLE
  62.     y AS SINGLE
  63.     dx AS SINGLE
  64.     dy AS SINGLE
  65.     size AS SINGLE
  66.     kolor AS _UNSIGNED LONG
  67.  
  68. TYPE bullet
  69.     x AS SINGLE
  70.     y AS SINGLE
  71.     dx AS SINGLE
  72.     dy AS SINGLE
  73.     live AS LONG
  74.  
  75. TYPE shipType
  76.     x AS SINGLE
  77.     y AS SINGLE
  78.     live AS LONG
  79.     speed AS SINGLE
  80.     thrustAngle AS SINGLE
  81.     angle AS SINGLE '   rotated position usu gun left or right (mouse button), maybe up press w or down press z
  82.     thruster AS LONG ' 1 forward, 2 reverse, 3 left , 4 right 0 none for drawing
  83.  
  84. TYPE rock
  85.     x AS SINGLE
  86.     y AS SINGLE
  87.     r AS LONG '            radius
  88.     ra AS SINGLE '         rotation position   a = a + spin
  89.     heading AS SINGLE '    heading from which dx, dy are calc with speed
  90.     speed AS SINGLE '      speed
  91.     spin AS SINGLE '       rotation direction and amount
  92.     seed AS LONG '         for drawing rocks with RND USING
  93.     c AS LONG '            color   rgb(c, c, c)
  94.     live AS LONG '         need this to track rocks still active like bullets
  95.     explodeFrame AS LONG ' after a rock is hit by bullet, it explodes and in more than one frame
  96.  
  97. REDIM SHARED aliens(1 TO 5) AS alienType
  98. DIM SHARED dots(2000) AS particle
  99. DIM SHARED b(nBullets) AS bullet
  100. DIM SHARED ship AS shipType
  101. DIM SHARED r(nRocks) AS rock
  102. DIM SHARED points AS LONG
  103. DIM SHARED rocks AS LONG 'rocks is the minimum number of parent rocks to have on screen  automatic replace when hit or out of bounds
  104.  
  105. DIM HS AS LONG, fnt AS LONG, fnt2 AS LONG ' file LOAD handles
  106. DIM i AS LONG, bullets AS LONG, fire AS LONG ' index and bullets
  107. DIM r AS LONG, newRockN AS LONG, maxBabyRocks AS LONG, br AS LONG, hits AS LONG ' rock stuff
  108. DIM ai AS LONG, alienN AS LONG ' alien index and number
  109. DIM hs$, s$, k$, t, lastt 'high score, general string and times for bullets
  110.  
  111. SCREEN _NEWIMAGE(xmax, ymax, 32)
  112. _SCREENMOVE 100, 20
  113.  
  114. fnt = _LOADFONT("ARLRDBD.ttf", 16, "MONOSPACE")
  115. fnt2 = _LOADFONT("ARLRDBD.ttf", 40, "MONOSPACE")
  116. _FONT fnt2
  117. COLOR &HFF00FFFF, &H00000000
  118.  
  119. IF _FILEEXISTS("Asteroids High Score.txt") THEN
  120.     OPEN "Asteroids High Score.txt" FOR INPUT AS #1
  121.     INPUT #1, HS
  122.     CLOSE #1
  123. hs$ = "High Score:" + STR$(HS)
  124.  
  125. 'a little splash screen
  126. rocks = 7: alienN = 3
  127. FOR i = 1 TO nRocks
  128.     newRock i
  129.     IF i > rocks THEN r(i).live = 0
  130. FOR i = 1 TO alienN
  131.     newAlien i
  132. i = 0
  133.     drawStars 0
  134.     i = i + 1
  135.     IF i MOD 30 = 29 AND rocks < nRocks THEN rocks = rocks + 1: r(rocks).live = 1
  136.     FOR r = 1 TO nRocks
  137.         IF r(r).live THEN drawRock r
  138.     NEXT
  139.     FOR i = 1 TO alienN
  140.         drawAliens i
  141.     NEXT
  142.     _FONT fnt2
  143.     s$ = "Asteroids AS-Space-KL"
  144.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 60), s$
  145.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(hs$)) / 2, 140), hs$
  146.     s$ = "A = Left spin"
  147.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 220), s$
  148.     s$ = "S = Right Spin"
  149.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 300), s$
  150.     s$ = "Space = Hyper jump"
  151.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 380), s$
  152.     s$ = "K = Thrust"
  153.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 460), s$
  154.     s$ = "L = Fire!"
  155.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 540), s$
  156.     _FONT fnt
  157.     k$ = INKEY$
  158.  
  159.     _DISPLAY
  160.     _LIMIT 60
  161.  
  162. restart:
  163. IF _FILEEXISTS("Asteroids High Score.txt") THEN
  164.     OPEN "Asteroids High Score.txt" FOR INPUT AS #1
  165.     INPUT #1, HS
  166.     CLOSE #1
  167. hs$ = "  High Score:" + STR$(HS)
  168. lives = 10: alienN = 1: rocks = 1: ' always active rocks
  169. points = 0: hits = 0: bullets = 0
  170. WHILE lives > 0 AND _KEYDOWN(27) = 0 ' init start restart
  171.     REDIM aliens(1 TO alienN) AS alienType
  172.     FOR ai = 1 TO alienN
  173.         newAlien ai
  174.     NEXT
  175.     FOR i = 1 TO nRocks 'reset rocks mainly clear baby rocks
  176.         newRock (i)
  177.         IF i > rocks THEN r(i).live = 0
  178.     NEXT
  179.     ship.x = xmax / 2 'avoids explosions top left corner at start, dang still get some!
  180.     ship.y = ymax / 2
  181.     ship.angle = 0
  182.     ship.thrustAngle = 0
  183.     ship.speed = 0
  184.     ship.live = 1
  185.     WHILE ship.live AND _KEYDOWN(27) = 0
  186.         k$ = INKEY$
  187.         'draw everything then process bullets
  188.         drawStars 1
  189.  
  190.         FOR ai = 1 TO alienN
  191.             drawAliens ai
  192.         NEXT
  193.         FOR i = 1 TO nRocks
  194.             IF r(i).live THEN drawRock i ' while drawing rocks the ship could be blown up
  195.             IF ((r(i).x - ship.x) ^ 2 + (r(i).y - ship.y) ^ 2) ^ .5 < r(i).r + 30 THEN 'rock collides with ship?
  196.                 FOR br = 1 TO 200 STEP 5
  197.                     CIRCLE ((ship.x + r(i).x) / 2, (ship.y + r(i).y) / 2), br, _RGB32(255 - br, 255 - 2 * br, 0)
  198.                 NEXT
  199.                 drawRock i
  200.                 drawship
  201.                 ship.live = 0
  202.                 IF i <= rocks THEN newRock i ELSE r(i).live = 0
  203.             END IF
  204.         NEXT
  205.         FOR i = 1 TO nRocks 'smoke up the place with rock debris fields still flying out from hit frames ago
  206.             IF r(i).explodeFrame THEN
  207.                 r(i).explodeFrame = r(i).explodeFrame + 1
  208.                 IF r(i).explodeFrame > .25 * r(i).r THEN
  209.                     r(i).explodeFrame = 0
  210.                     IF i <= rocks THEN newRock i ' now replace the rock
  211.                 ELSE
  212.                     explode r(i).x, r(i).y, r(i).r, r(i).explodeFrame
  213.                 END IF
  214.             END IF
  215.         NEXT
  216.         IF ship.live THEN
  217.             FOR ai = 1 TO alienN
  218.                 IF SQR((aliens(ai).x - ship.x) ^ 2 + (aliens(ai).y - ship.y) ^ 2) < 60 THEN 'aliens and ship collisde boom boom
  219.                     FOR br = 1 TO 200 STEP 5
  220.                         CIRCLE ((ship.x + aliens(ai).x) / 2, (ship.y + aliens(ai).y) / 2), br, _RGB32(255 - br, 255 - 2 * br, 0)
  221.                     NEXT
  222.                     drawship
  223.                     ship.live = 0
  224.                     _CONTINUE
  225.                 ELSE
  226.                     drawship
  227.                 END IF
  228.             NEXT
  229.  
  230.             ' ship update
  231.             ship.thruster = 0 ' reset
  232.  
  233.  
  234.             IF _KEYDOWN(ASC("a")) THEN ship.angle = ship.angle - pi / 90: ship.thruster = 4
  235.             IF _KEYDOWN(ASC("s")) THEN ship.angle = ship.angle + pi / 90: ship.thruster = 3
  236.             IF k$ = "k" THEN ship.speed = ship.speed + 3: ship.thrustAngle = ship.angle: ship.thruster = 1
  237.             IF k$ = "l" THEN 'l =fire
  238.                 fire = 0
  239.                 t = TIMER(.01)
  240.                 IF lastt = 0 OR t - lastt > .1 THEN fire = 1: lastt = t
  241.             END IF
  242.             IF k$ = " " THEN 'hyperspace
  243.                 ship.x = (xmax - 200) * RND + 100: ship.y = (ymax - 200) * RND + 100: ship.speed = 0
  244.             END IF
  245.  
  246.             'locate ship
  247.             ship.x = ship.x + ship.speed * COS(ship.thrustAngle)
  248.             ship.y = ship.y + ship.speed * SIN(ship.thrustAngle)
  249.             ship.speed = ship.speed - .02
  250.             IF ship.speed < 0 THEN ship.speed = 0
  251.  
  252.  
  253.             IF ship.x < 0 THEN ship.x = xmax - ABS(ship.x)
  254.             IF ship.x > xmax THEN ship.x = ship.x - xmax
  255.             IF ship.y < 0 THEN ship.y = ymax - ABS(ship.y)
  256.             IF ship.y > ymax THEN ship.y = ship.y - ymax
  257.  
  258.  
  259.             FOR i = 0 TO nBullets 'handle bullets
  260.                 IF b(i).live = 0 AND fire = 1 THEN 'have inactive bullet to use
  261.                     b(i).x = ship.x + bSpeed * COS(ship.angle)
  262.                     b(i).y = ship.y + bSpeed * SIN(ship.angle)
  263.                     b(i).dx = bSpeed * COS(ship.angle)
  264.                     b(i).dy = bSpeed * SIN(ship.angle)
  265.                     b(i).live = -1
  266.                     bullets = bullets + 1
  267.                     fire = 0
  268.                 END IF
  269.                 IF b(i).live THEN 'new location
  270.                     b(i).x = b(i).x + b(i).dx
  271.                     b(i).y = b(i).y + b(i).dy
  272.                     IF b(i).x > 0 AND b(i).x < xmax AND b(i).y > 0 AND b(i).y < ymax THEN 'in bounds draw it
  273.  
  274.                         'bullet hit aliens?
  275.                         FOR ai = 1 TO alienN
  276.                             IF SQR((aliens(ai).x - b(i).x) ^ 2 + (aliens(ai).y - b(i).y) ^ 2) < 30 THEN
  277.                                 FOR br = 1 TO 120
  278.                                     CIRCLE (aliens(ai).x, aliens(ai).y), br / 3, plasma~&(0)
  279.                                 NEXT
  280.                                 _DISPLAY
  281.                                 _DELAY .05
  282.                                 hits = hits + 1
  283.                                 points = points + 100
  284.                                 aliens(ai).live = 0
  285.                                 newAlien ai
  286.                                 b(i).live = 0
  287.                                 _CONTINUE
  288.                             END IF
  289.                         NEXT
  290.                         FOR r = 1 TO nRocks 'check for collision with rock
  291.                             IF r(r).live THEN
  292.                                 IF SQR((r(r).x - b(i).x) ^ 2 + (r(r).y - b(i).y) ^ 2) < r(r).r THEN 'its a hit!
  293.                                     r(r).explodeFrame = 1 'linger with explosion
  294.                                     r(r).live = 0
  295.                                     hits = hits + 1
  296.                                     points = points + ((r(r).speed - .5) * 50 + (90 - (r(r).r - 10)) * 1.1111) / 2
  297.                                     IF r(r).r > 30 THEN '       split rock  into ? new ones
  298.                                         maxBabyRocks = INT((r(r).r - 10) / 10)
  299.                                         maxBabyRocks = irnd&(2, maxBabyRocks) ' pick a number of baby Rocks
  300.                                         FOR br = 1 TO maxBabyRocks
  301.                                             '                        new rock
  302.                                             newRockN = freeRock& '                          get inactive rock number
  303.                                             newRock newRockN '                              new identity and activate
  304.                                             r(newRockN).r = (r(r).r - 10) / maxBabyRocks '  split in equal parts minus 20% mass
  305.                                             r(newRockN).x = r(r).x + irnd&(-30, 30) '       thrown from parent
  306.                                             r(newRockN).y = r(r).y + irnd&(-30, 30)
  307.                                             r(newRockN).c = r(r).c '                   same color as parent
  308.                                             r(newRockN).heading = rrnd(ship.angle - .75 * pi, ship.angle + .75 * pi)
  309.                                         NEXT
  310.                                     END IF ' big enough to split
  311.                                     b(i).live = 0 'kill bullet
  312.                                 END IF ' hit rock
  313.                             END IF 'rock is there
  314.                         NEXT ' rock
  315.                         IF b(i).live THEN fcirc b(i).x, b(i).y, 3, _RGB32(255, 255, 0) 'draws bullet
  316.                     ELSE
  317.                         b(i).live = 0 'out of bounds
  318.                     END IF ' bullet is in bounds
  319.                 END IF ' bullet live
  320.             NEXT ' bullet
  321.         END IF ' if ship still live
  322.         _DISPLAY
  323.         IF ship.live = 0 THEN
  324.             lives = lives - 1
  325.             IF lives MOD 4 = 0 THEN rocks = rocks + 1
  326.             IF lives MOD 4 = 2 THEN alienN = alienN + 1
  327.             s$ = "Lives:" + STR$(lives) + "  Hits:" + STR$(hits) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits * 100 / bullets)) + "%"
  328.             _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 80), s$
  329.             _FONT fnt2
  330.             s$ = STR$(points) + hs$
  331.             _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  332.             _FONT fnt
  333.             s$ = "Press Enter to enter your next life"
  334.             _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 + 120), s$
  335.             _DISPLAY
  336.             _MOUSESHOW
  337.             WHILE _KEYDOWN(13) = 0: WEND 'wait for enter key
  338.         ELSE
  339.             _LIMIT 30 ' if ship dies let's rest and regroup  before restart next life
  340.         END IF
  341.     WEND
  342.     _DISPLAY
  343. IF points > HS THEN
  344.     OPEN "Asteroids High Score.txt" FOR OUTPUT AS #1
  345.     PRINT #1, points
  346.     CLOSE #1
  347. ship.x = -200: ship.y = -200 'get it out of the way
  348. i = 0
  349.     drawStars 0
  350.     i = i + 1
  351.     IF i MOD 30 = 29 AND rocks < nRocks THEN rocks = rocks + 1: r(rocks).live = 1
  352.     FOR r = 1 TO nRocks
  353.         IF r(r).live THEN drawRock r
  354.     NEXT
  355.     s$ = "Lives:" + STR$(lives) + "  Hits:" + STR$(hits) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits * 100 / bullets)) + "%"
  356.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 80), s$
  357.     _FONT fnt2
  358.     s$ = STR$(points)
  359.     IF points > HS THEN s$ = s$ + " a New Record!" ELSE s$ = STR$(points) + hs$
  360.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  361.     _FONT fnt
  362.     s$ = "Press q to quit, p or a to Play Again..."
  363.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 + 120), s$
  364.     IF _KEYDOWN(ASC("a")) OR _KEYDOWN(ASC("p")) THEN GOTO restart
  365.     _DISPLAY
  366.     _LIMIT 60
  367.  
  368. SUB drawStars (moving)
  369.     TYPE starType
  370.         x AS SINGLE
  371.         y AS SINGLE
  372.         size AS SINGLE
  373.         c AS INTEGER
  374.     END TYPE
  375.     STATIC beenHere, stars(600) AS starType, cy AS LONG
  376.     DIM i AS LONG
  377.     IF beenHere = 0 THEN 'static part
  378.         FOR i = 0 TO 200
  379.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = 0
  380.             stars(i).c = irnd&(80, 140)
  381.         NEXT
  382.         FOR i = 0 TO 200
  383.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = .3
  384.             stars(i).c = irnd&(80, 140)
  385.         NEXT
  386.  
  387.         FOR i = 1 TO 140
  388.             stars(i + 400).x = RND * xmax: stars(i + 400).y = RND * ymax: stars(i + 100).size = .6
  389.             stars(i).c = irnd&(110, 170)
  390.         NEXT
  391.         FOR i = 1 TO 50
  392.             stars(i + 540).x = RND * xmax: stars(i + 540).y = RND * ymax: stars(i + 170).size = 1.2
  393.             stars(i).c = irnd&(140, 200)
  394.         NEXT
  395.         FOR i = 1 TO 10
  396.             stars(i + 590).x = RND * xmax: stars(i + 590).y = RND * ymax: stars(i + 195).size = 2.4
  397.             stars(i).c = irnd&(170, 235)
  398.         NEXT
  399.         cy = ymax / 2
  400.         beenHere = 1
  401.     END IF
  402.     FOR i = 0 TO cy
  403.         LINE (0, i)-(xmax, i), _RGB32(0, 0, .1 * i + 4)
  404.         LINE (0, ymax - i)-(xmax, ymax - i), _RGB(0, 0, .1 * i + 4)
  405.     NEXT
  406.     FOR i = 0 TO 200
  407.         IF moving THEN
  408.             stars(i).x = stars(i).x + .2 * stars(i).size ^ stars(i).size
  409.             IF stars(i).x > xmax THEN stars(i).x = -1 * RND * 20
  410.         END IF
  411.         fcirc stars(i).x, stars(i).y, stars(i).size, _RGB32(stars(i).c - 10, stars(i).c, stars(i).c + 10)
  412.     NEXT
  413.  
  414. SUB newAlien (i AS LONG)
  415.     DIM side AS LONG, heading
  416.     RANDOMIZE TIMER * RND 'to avoid making twins
  417.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  418.     aliens(i).fireX = irnd(10, xmax - 10)
  419.     aliens(i).fireY = irnd(10, ymax - 10)
  420.     aliens(i).attackFrame = irnd(30, 400) ' EDIT a tweak to survive a little long before getting murdered with low lives over and over...
  421.     SELECT CASE side
  422.         CASE 1
  423.             aliens(i).x = -10
  424.             aliens(i).y = rrnd(20, ymax - 20)
  425.         CASE 2
  426.             aliens(i).x = xmax + 10
  427.             aliens(i).y = rrnd(20, ymax - 20)
  428.         CASE 3
  429.             aliens(i).x = rrnd(20, xmax - 20)
  430.             aliens(i).y = -10
  431.         CASE 4
  432.             aliens(i).x = rrnd(20, xmax - 20)
  433.             aliens(i).y = ymax + 10
  434.     END SELECT
  435.     heading = _ATAN2(aliens(i).fireY - aliens(i).y, aliens(i).fireX - aliens(i).x)
  436.     aliens(i).dx = .5 * COS(heading)
  437.     aliens(i).dy = .5 * SIN(heading)
  438.     aliens(i).live = 0
  439.     aliens(i).transform = 0
  440.     aliens(i).c = _RGB32(irnd(128, 255), irnd(0, 255), irnd(0, 255))
  441.  
  442. FUNCTION plasma~& (new AS LONG)
  443.     STATIC r, g, b, cnt, beenHere
  444.     IF beenHere = 0 OR new THEN
  445.         r = RND: g = RND: b = RND: beenHere = 1: cnt = 0
  446.     END IF
  447.     cnt = cnt + .2
  448.     plasma~& = _RGB32(127 + 127 * SIN(r * cnt), 127 + 127 * SIN(g * cnt), 127 + 127 * SIN(b * cnt))
  449.  
  450. SUB drawAliens (i AS LONG) 'shipType
  451.     DIM light AS LONG, heading, r AS LONG, g AS LONG, b AS LONG
  452.     IF aliens(i).live THEN
  453.         IF aliens(i).transform = 0 THEN
  454.             r = _RED32(aliens(i).c): g = _GREEN32(aliens(i).c): b = _BLUE32(aliens(i).c)
  455.             fellipse aliens(i).x, aliens(i).y, 6, 15, _RGB32(r, g - 120, b - 100)
  456.             fellipse aliens(i).x, aliens(i).y, 18, 11, _RGB32(r, g - 60, b - 50)
  457.             fellipse aliens(i).x, aliens(i).y, 30, 7, _RGB32(r, g, b)
  458.             FOR light = 0 TO 5
  459.                 fcirc aliens(i).x - 30 + 11 * light + aliens(i).ls, aliens(i).y, 1, _RGB32(aliens(i).ls * 50, aliens(i).ls * 50, aliens(i).ls * 50)
  460.             NEXT
  461.             aliens(i).ls = aliens(i).ls + 1
  462.             IF aliens(i).ls > 5 THEN aliens(i).ls = 0
  463.         ELSE
  464.             drawBall aliens(i).x, aliens(i).y, 30, aliens(i).c
  465.         END IF
  466.         'time to shoot?
  467.         aliens(i).x = aliens(i).x + aliens(i).dx
  468.         aliens(i).y = aliens(i).y + aliens(i).dy
  469.         IF SQR((aliens(i).fireX - aliens(i).x) ^ 2 + (aliens(i).fireY - aliens(i).y) ^ 2) < 5 THEN 'transform into the bolder of death
  470.             aliens(i).transform = 1
  471.             heading = _ATAN2(ship.y - aliens(i).y, ship.x - aliens(i).x)
  472.             aliens(i).dx = 2.5 * COS(heading)
  473.             aliens(i).dy = 2.5 * SIN(heading)
  474.         END IF
  475.         IF aliens(i).x < -10 OR aliens(i).x > xmax + 10 THEN
  476.             IF aliens(i).y < -10 OR aliens(i).y > ymax + 10 THEN '  out of bounds goodbye bolder of death!
  477.                 aliens(i).live = 0 'man we dodged a bullet here!!!!
  478.                 newAlien i 'reset the trap
  479.             END IF
  480.         END IF
  481.     ELSE
  482.         IF aliens(i).attackFrame THEN
  483.             aliens(i).attackFrame = aliens(i).attackFrame - 1
  484.             IF aliens(i).attackFrame = 0 THEN
  485.                 aliens(i).live = 1
  486.             END IF
  487.         END IF
  488.     END IF
  489.  
  490. FUNCTION freeRock&
  491.     DIM i AS LONG
  492.     FOR i = rocks + 1 TO nRocks ' look for inactive rock number
  493.         IF r(i).live = 0 AND r(i).explodeFrame = 0 THEN freeRock& = i: EXIT FUNCTION
  494.     NEXT
  495.  
  496. SUB explode (x AS LONG, y AS LONG, r AS LONG, frm AS LONG)
  497.     DIM maxParticles AS LONG, i AS LONG, rounds AS LONG, loopCount AS LONG
  498.     maxParticles = r * 4
  499.     FOR i = 1 TO r
  500.         NewDot i, x, y, r
  501.     NEXT
  502.     rounds = r
  503.     FOR loopCount = 0 TO frm
  504.         IF _KEYDOWN(27) THEN END
  505.         FOR i = 1 TO rounds
  506.             dots(i).x = dots(i).x + dots(i).dx
  507.             dots(i).y = dots(i).y + dots(i).dy
  508.             fcirc dots(i).x, dots(i).y, dots(i).size, dots(i).kolor
  509.         NEXT
  510.         IF rounds < maxParticles THEN
  511.             FOR i = 1 TO r
  512.                 NewDot (rounds + i), x, y, r
  513.             NEXT
  514.             rounds = rounds + r
  515.         END IF
  516.     NEXT
  517.  
  518. SUB NewDot (i AS LONG, x AS LONG, y AS LONG, r AS LONG)
  519.     DIM angle, rd
  520.     angle = pi * 2 * RND
  521.     rd = RND * 30
  522.     dots(i).x = x + rd * COS(angle)
  523.     dots(i).y = y + rd * SIN(angle)
  524.     dots(i).size = RND * r * .05
  525.     rd = RND 'STxAxTIC recommended for rounder spreads
  526.     dots(i).dx = rd * 10 * (10 - 2 * dots(i).size) * COS(angle)
  527.     dots(i).dy = rd * 10 * (10 - 2 * dots(i).size) * SIN(angle)
  528.     rd = 20 + RND * 70
  529.     dots(i).kolor = _RGBA32(rd, rd, rd, 80)
  530.  
  531. SUB drawship 'simple red iso triangle pointed towards radianAngle
  532.     DIM x1 AS LONG, y1 AS LONG, x2 AS LONG, y2 AS LONG, x3 AS LONG, y3 AS LONG
  533.     DIM x4 AS LONG, y4 AS LONG, x5 AS LONG, y5 AS LONG, x6 AS LONG, y6 AS LONG
  534.     DIM x7 AS LONG, y7 AS LONG
  535.  
  536.  
  537.     'calculate 3 points of triangle ship
  538.     fcirc ship.x, ship.y, 30, &H05FFFFFF
  539.     x1 = ship.x + 30 * COS(ship.angle) ' front point
  540.     y1 = ship.y + 30 * SIN(ship.angle) '
  541.     x2 = ship.x + 30 * COS(ship.angle + .6666 * pi) ' wing
  542.     y2 = ship.y + 30 * SIN(ship.angle + .6666 * pi)
  543.     x3 = ship.x + 30 * COS(ship.angle - .6666 * pi) ' other wing
  544.     y3 = ship.y + 30 * SIN(ship.angle - .6666 * pi)
  545.     ftri ship.x, ship.y, x1, y1, x2, y2, _RGB32(80, 120, 80, 80)
  546.     ftri ship.x, ship.y, x1, y1, x3, y3, _RGB32(60, 100, 60, 80)
  547.     LINE (x1, y1)-(ship.x, ship.y), _RGB32(255, 255, 128)
  548.     LINE (x1, y1)-(x2, y2), _RGB32(180, 180, 120)
  549.     LINE (x1, y1)-(x3, y3), _RGB32(180, 180, 120)
  550.  
  551.     SELECT CASE ship.thruster
  552.         CASE 1 'forward apex = ship.x, ship,y  direction = ship.angle + pi
  553.             x4 = ship.x + 25 * COS(ship.angle - 17 / 18 * pi)
  554.             y4 = ship.y + 25 * SIN(ship.angle - 17 / 18 * pi)
  555.             x5 = ship.x + 25 * COS(ship.angle - 19 / 18 * pi)
  556.             y5 = ship.y + 25 * SIN(ship.angle - 19 / 18 * pi)
  557.             ftri ship.x, ship.y, x4, y4, x5, y5, &H99FFFF88
  558.         CASE 2 'reverse apex = x1, y1
  559.             x6 = x2 + 25 * COS(ship.angle + 1 / 18 * pi)
  560.             y6 = y2 + 25 * SIN(ship.angle + 1 / 18 * pi)
  561.             x7 = x2 + 25 * COS(ship.angle - 1 / 18 * pi)
  562.             y7 = y2 + 25 * SIN(ship.angle - 1 / 18 * pi)
  563.             ftri x2, y2, x6, y6, x7, y7, &H99FFFF88
  564.  
  565.             x6 = x3 + 25 * COS(ship.angle + 1 / 18 * pi)
  566.             y6 = y3 + 25 * SIN(ship.angle + 1 / 18 * pi)
  567.             x7 = x3 + 25 * COS(ship.angle - 1 / 18 * pi)
  568.             y7 = y3 + 25 * SIN(ship.angle - 1 / 18 * pi)
  569.             ftri x3, y3, x6, y6, x7, y7, &H99FFFF88
  570.         CASE 3 'left apex = x2, y2
  571.             x6 = x3 + 25 * COS(ship.angle - 17 / 18 * pi)
  572.             y6 = y3 + 25 * SIN(ship.angle - 17 / 18 * pi)
  573.             x7 = x3 + 25 * COS(ship.angle - 19 / 18 * pi)
  574.             y7 = y3 + 25 * SIN(ship.angle - 19 / 18 * pi)
  575.             ftri x3, y3, x6, y6, x7, y7, &H99FFFF88
  576.  
  577.             'x6 = x2 + 25 * COS(ship.angle + 1 / 18 * pi)
  578.             'y6 = y2 + 25 * SIN(ship.angle + 1 / 18 * pi)
  579.             'x7 = x2 + 25 * COS(ship.angle - 1 / 18 * pi)
  580.             'y7 = y2 + 25 * SIN(ship.angle - 1 / 18 * pi)
  581.             'ftri x2, y2, x6, y6, x7, y7, &H99FFFF88
  582.         CASE 4 'right
  583.             x6 = x2 + 25 * COS(ship.angle - 17 / 18 * pi)
  584.             y6 = y2 + 25 * SIN(ship.angle - 17 / 18 * pi)
  585.             x7 = x2 + 25 * COS(ship.angle - 19 / 18 * pi)
  586.             y7 = y2 + 25 * SIN(ship.angle - 19 / 18 * pi)
  587.             ftri x2, y2, x6, y6, x7, y7, &H99FFFF88
  588.  
  589.             'x6 = x3 + 25 * COS(ship.angle + 1 / 18 * pi)
  590.             'y6 = y3 + 25 * SIN(ship.angle + 1 / 18 * pi)
  591.             'x7 = x3 + 25 * COS(ship.angle - 1 / 18 * pi)
  592.             'y7 = y3 + 25 * SIN(ship.angle - 1 / 18 * pi)
  593.             'ftri x3, y3, x6, y6, x7, y7, &H99FFFF88
  594.     END SELECT
  595.  
  596. SUB drawRock (iRock)
  597.     RANDOMIZE USING r(iRock).seed 'this prevents having to save a particular sequence of random number
  598.     DIM dx, dy, j AS LONG, rRad AS SINGLE, leg AS SINGLE, x0 AS LONG, y0 AS LONG, rc AS LONG, c~&, x1 AS LONG, y1 AS LONG, xoff, yoff, i AS LONG
  599.     DIM x2 AS LONG, y2 AS LONG
  600.     dx = r(iRock).speed * COS(r(iRock).heading)
  601.     dy = r(iRock).speed * SIN(r(iRock).heading) 'update location
  602.     r(iRock).ra = r(iRock).ra + r(iRock).spin
  603.     IF r(iRock).x + dx + r(iRock).r < 0 OR r(iRock).x + dx - r(iRock).r > xmax OR r(iRock).y + dy + r(iRock).r < 0 OR r(iRock).y + dy - r(iRock).r > ymax THEN
  604.         IF iRock <= rocks THEN newRock iRock ELSE r(iRock).live = 0
  605.         EXIT SUB ' reassigned get out of here
  606.     ELSE
  607.         r(iRock).x = r(iRock).x + dx
  608.         r(iRock).y = r(iRock).y + dy
  609.     END IF
  610.     FOR j = 10 TO 3 STEP -1 '                  rock drawing (see demo program where developed code)
  611.         rRad = .1 * j * r(iRock).r
  612.         leg = rRad * (RND * .7 + .3)
  613.         x0 = r(iRock).x + leg * COS(r(iRock).ra)
  614.         y0 = r(iRock).y + leg * SIN(r(iRock).ra)
  615.         rc = r(iRock).c + 30 * RND - 15
  616.         c~& = _RGB32(rc + 5, rc - 10, rc + 5)
  617.         x1 = x0
  618.         y1 = y0
  619.         xoff = RND * 20 - 10 + r(iRock).x
  620.         yoff = RND * 20 - 10 + r(iRock).y
  621.         FOR i = 1 TO 12
  622.             leg = rRad * (RND * .35 + .65)
  623.             IF i = 12 THEN
  624.                 x2 = x0: y2 = y0
  625.             ELSE
  626.                 x2 = xoff + leg * COS(i * polyAngle + r(iRock).ra)
  627.                 y2 = yoff + leg * SIN(i * polyAngle + r(iRock).ra)
  628.             END IF
  629.             ftri r(iRock).x, r(iRock).y, x1, y1, x2, y2, c~&
  630.             x1 = x2: y1 = y2
  631.         NEXT
  632.     NEXT
  633.  
  634. SUB newRock (iRock)
  635.     DIM side AS LONG
  636.     RANDOMIZE TIMER * RND 'to avoid making twins
  637.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  638.     SELECT CASE side
  639.         CASE 1
  640.             r(iRock).x = -100
  641.             r(iRock).y = rrnd(20, ymax - 20)
  642.             r(iRock).heading = 3 * pi / 2 + RND * pi
  643.         CASE 2
  644.             r(iRock).x = xmax + 100
  645.             r(iRock).y = rrnd(20, ymax - 20)
  646.             r(iRock).heading = pi / 2 + RND * pi
  647.         CASE 3
  648.             r(iRock).x = rrnd(20, xmax - 20)
  649.             r(iRock).y = -100
  650.             r(iRock).heading = RND * pi
  651.         CASE 4
  652.             r(iRock).x = rrnd(20, xmax - 20)
  653.             r(iRock).y = ymax + 100
  654.             r(iRock).heading = pi + RND * pi
  655.     END SELECT
  656.     r(iRock).speed = rrnd(.5, 2.5) 'speed, rotation angle, radius, gray coloring, spin, seed, hit for explosion
  657.     r(iRock).ra = RND * 2 * pi
  658.     r(iRock).r = irnd&(30, 100)
  659.     r(iRock).c = irnd&(60, 110) ' Ken request increase in rock color
  660.     r(iRock).spin = rrnd(-pi / 20, pi / 20)
  661.     r(iRock).seed = INT(RND * 64000) - 32000
  662.     r(iRock).explodeFrame = 0
  663.     r(iRock).live = 1
  664.  
  665. FUNCTION irnd& (n1, n2) 'return an integer between 2 numbers
  666.     DIM l%, h%
  667.     IF n1 > n2 THEN l% = n2: h% = n1 ELSE l% = n1: h% = n2
  668.     irnd& = INT(RND * (h% - l% + 1)) + l%
  669.  
  670. FUNCTION rrnd (n1, n2) ' return number (expecting reals =_single, double, _float depending on default / define setup)
  671.     rrnd = (n2 - n1) * RND + n1
  672.  
  673. SUB drawBall (x, y, r, c AS _UNSIGNED LONG)
  674.     DIM red AS LONG, grn AS LONG, blu AS LONG, rr AS LONG, f
  675.     red = _RED32(c): grn = _GREEN32(c): blu = _BLUE32(c)
  676.     FOR rr = r TO 0 STEP -1
  677.         f = 1 - rr / r
  678.         fcirc x, y, rr, _RGB32(red * f, grn * f, blu * f)
  679.     NEXT
  680.  
  681. SUB fellipse (CX AS LONG, CY AS LONG, xr AS LONG, yr AS LONG, C AS _UNSIGNED LONG)
  682.     IF xr = 0 OR yr = 0 THEN EXIT SUB
  683.     DIM x AS LONG, y AS LONG
  684.     w2 = xr * xr: h2 = yr * yr: h2w2 = h2 * w2
  685.     LINE (CX - xr, CY)-(CX + xr, CY), C, BF
  686.     DO WHILE y < yr
  687.         y = y + 1
  688.         x = SQR((h2w2 - y * y * w2) \ h2)
  689.         LINE (CX - x, CY + y)-(CX + x, CY + y), C, BF
  690.         LINE (CX - x, CY - y)-(CX + x, CY - y), C, BF
  691.     LOOP
  692.  
  693. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  694.     DIM D AS LONG
  695.     STATIC a&
  696.     D = _DEST
  697.     IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32)
  698.     _DEST a&
  699.     _DONTBLEND a& '  '<<<< new 2019-12-16 fix
  700.     PSET (0, 0), K
  701.     _BLEND a& '<<<< new 2019-12-16 fix
  702.     _DEST D
  703.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  704.  
  705. SUB fcirc (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG) 'vince version
  706.     DIM x0 AS LONG, y0 AS LONG, e AS LONG
  707.     x0 = R: y0 = 0: e = 0
  708.     DO WHILE y0 < x0
  709.         IF e <= 0 THEN
  710.             y0 = y0 + 1
  711.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  712.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  713.             e = e + 2 * y0
  714.         ELSE
  715.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  716.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  717.             x0 = x0 - 1: e = e - 2 * x0
  718.         END IF
  719.     LOOP
  720.     LINE (x - R, y)-(x + R, y), C, BF
  721.  

Don't knock yourself out with this, I am going to reinstall latest thrust changes I just posted (where ship.speed is constant).

But if you or anyone can solve the mysterious disappearance of Hyperdrive spacebar  after the first use, I probably would be grateful or disgusted by my blunder ha, ha! But live and learn!

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: b+ Asteroids makeover
« Reply #64 on: November 04, 2020, 02:33:52 pm »
Here you go B+. :) You will hate me when I tell you how I fixed it. It's something you guys have told me not to use more than once in an entire program but it works. I added RANDOMIZE TIMER right before the RND lines. I also changed the INKEY$ to KEYHIT since it seemed to work better, but you can try INKEY$ again if you want. What I found out was that it was actually working every time with KEYHIT (and possibly INKEY$) but it was just going to the same location you started at. For example, if I moved and used it, it went back to where it was before, almost every time. So that meant it was a randomize problem so RANDOMIZE TIMER does the trick. :) For some reason it needed to randomize the timer again probably since it also uses RND in other locations in your program. Oh, as I experimented with different things I also removed XMAX and YMAX and just used your values of it instead to make it easier on the program. That probably doesn't do anything though but I left it there.

Here is the code. It's where I added the '------------------- line, but you know where I'm talking about.

Code: QB64: [Select]
  1. _TITLE "b+ Asteroids m9 AS-Space-KL " 'started 2018-07-13"
  2.  
  3. '                                            New Controls
  4. ' key a = turn left
  5. ' key s = turn right
  6. '          spacebar =  "hyperspace" show up somewhere else  better or worse use when collision is imminent
  7. ' key k = thrust  just a burst in direction you are pointed but doesn't last
  8. ' key l = fire! owwha, owha, owha...
  9.  
  10. '=================================================================================================================
  11.  
  12. ' 2020-10-27 remove the alternate subs and get down below 200 LOC almost there now! new shooter action font and background
  13. ' 2020-10-28 another makeover explosions and split asteroids
  14. ' 2020-10-29 fix baby rock management, break between lives
  15. ' 2020-10-29 fix left/right gun, fix explosions over many frames to eliminate pause in action, speed up 60 fps
  16. ' 2020-10-30 m3 SierraKen's idea to angle shooter with mousewheel also finish WASD options, more rocks, points system
  17. ' points:
  18. ' The higher the speed the better    speed range .5 to 2.5, diff = 2 * 50 = 100          s - .5 * 50
  19. ' DELETE The lower the color the better   color range 10 to 60, diff =      50 * 2 = 100  50 - (c - 10) * 2
  20. ' The smaller the size the better  size range 10 to 100, diff = 90 * 1.1111 = 100  90 - (sz -10) * 1.1111
  21. '        ((speed - .5) * 50 + (90 - (r - 10)) * 1.1111) / 2 = 100 best score per hit
  22. ' 2020-10-30 increase level of difficulty, fix double lives lost, add an ending after all lives spent.
  23. ' 2020-10-31 M4 They are Here - the aliens have accepted my invitaion for war games don't get caught in their beam.
  24. ' rework ending and variable LONG suffix. Aliens on the attack 100 points before or after transformed into the Bolder of Death.
  25. ' 2020-11-01 M5 FX Moving through space, Oh yeah, more aliens!
  26. ' 2020-11-01 M6 add play again and save high game , continuous shoot
  27. ' 2020-11-01 M7 fix hits count when hit alien ship or Bolder of Death. Fix lights on aliens ship. I want to see collsions with ship.
  28. ' Ken recommends removing text in middle of screen, yeah, distracting. Makeover ship as with mouse x, y it's center. Add Splash screen.
  29. ' Show mouse in between lives so can be in screen center when press key to start next run.
  30.  
  31. ' 2020-11-03 watching videos on Asteroids, I found a view and description of the control panel, it is:
  32. ' 2 buttons on left and lower button in middle and 2 buttons on right level with 2 on left
  33. ' 2 buttons on left are left and right turns they will be Keys A and S
  34. ' the middle will be spacebar for Hypespace or these days we might call it worm hole, jump to another location better or worse!
  35. ' 2 buttons on right K and L: K will be a thruster of sorts you evetually come to a stop L is the fire button
  36. ' So let's try that. I am impressed by hitting thruster and shooting all around as you dift in direction gun was pionted when hit thruster.
  37. ' Lighten rocks change points without rock color
  38.  
  39. '================================================================================================================
  40.  
  41. '    NOTE: !!!!!!!!!!!!!!!   When there is a pause in action, just hit = enter,  as in enter a new life!
  42.  
  43. '================================================================================================================
  44.  
  45. CONST xmax = 1200, ymax = 700, pi = _PI, polyAngle = _PI / 6, nRocks = 300, nBullets = 2000, bSpeed = 15
  46.  
  47. TYPE alienType
  48.     x AS SINGLE
  49.     y AS SINGLE
  50.     dx AS SINGLE
  51.     dy AS SINGLE
  52.     ls AS LONG ' lights offset
  53.     c AS _UNSIGNED LONG ' color
  54.     live AS LONG
  55.     attackFrame AS LONG
  56.     fireX AS SINGLE
  57.     fireY AS SINGLE
  58.     transform AS LONG
  59.  
  60. TYPE particle
  61.     x AS SINGLE
  62.     y AS SINGLE
  63.     dx AS SINGLE
  64.     dy AS SINGLE
  65.     size AS SINGLE
  66.     kolor AS _UNSIGNED LONG
  67.  
  68. TYPE bullet
  69.     x AS SINGLE
  70.     y AS SINGLE
  71.     dx AS SINGLE
  72.     dy AS SINGLE
  73.     live AS LONG
  74.  
  75. TYPE shipType
  76.     x AS SINGLE
  77.     y AS SINGLE
  78.     live AS LONG
  79.     speed AS SINGLE
  80.     thrustAngle AS SINGLE
  81.     angle AS SINGLE '   rotated position usu gun left or right (mouse button), maybe up press w or down press z
  82.     thruster AS LONG ' 1 forward, 2 reverse, 3 left , 4 right 0 none for drawing
  83.  
  84. TYPE rock
  85.     x AS SINGLE
  86.     y AS SINGLE
  87.     r AS LONG '            radius
  88.     ra AS SINGLE '         rotation position   a = a + spin
  89.     heading AS SINGLE '    heading from which dx, dy are calc with speed
  90.     speed AS SINGLE '      speed
  91.     spin AS SINGLE '       rotation direction and amount
  92.     seed AS LONG '         for drawing rocks with RND USING
  93.     c AS LONG '            color   rgb(c, c, c)
  94.     live AS LONG '         need this to track rocks still active like bullets
  95.     explodeFrame AS LONG ' after a rock is hit by bullet, it explodes and in more than one frame
  96.  
  97. REDIM SHARED aliens(1 TO 5) AS alienType
  98. DIM SHARED dots(2000) AS particle
  99. DIM SHARED b(nBullets) AS bullet
  100. DIM SHARED ship AS shipType
  101. DIM SHARED r(nRocks) AS rock
  102. DIM SHARED points AS LONG
  103. DIM SHARED rocks AS LONG 'rocks is the minimum number of parent rocks to have on screen  automatic replace when hit or out of bounds
  104.  
  105. DIM HS AS LONG, fnt AS LONG, fnt2 AS LONG ' file LOAD handles
  106. DIM i AS LONG, bullets AS LONG, fire AS LONG ' index and bullets
  107. DIM r AS LONG, newRockN AS LONG, maxBabyRocks AS LONG, br AS LONG, hits AS LONG ' rock stuff
  108. DIM ai AS LONG, alienN AS LONG ' alien index and number
  109. DIM hs$, s$, k$, t, lastt 'high score, general string and times for bullets
  110.  
  111. SCREEN _NEWIMAGE(xmax, ymax, 32)
  112. _SCREENMOVE 100, 20
  113.  
  114. fnt = _LOADFONT("ARLRDBD.ttf", 16, "MONOSPACE")
  115. fnt2 = _LOADFONT("ARLRDBD.ttf", 40, "MONOSPACE")
  116. _FONT fnt2
  117. COLOR &HFF00FFFF, &H00000000
  118.  
  119. IF _FILEEXISTS("Asteroids High Score.txt") THEN
  120.     OPEN "Asteroids High Score.txt" FOR INPUT AS #1
  121.     INPUT #1, HS
  122.     CLOSE #1
  123. hs$ = "High Score:" + STR$(HS)
  124.  
  125. 'a little splash screen
  126. rocks = 7: alienN = 3
  127. FOR i = 1 TO nRocks
  128.     newRock i
  129.     IF i > rocks THEN r(i).live = 0
  130. FOR i = 1 TO alienN
  131.     newAlien i
  132. i = 0
  133.     drawStars 0
  134.     i = i + 1
  135.     IF i MOD 30 = 29 AND rocks < nRocks THEN rocks = rocks + 1: r(rocks).live = 1
  136.     FOR r = 1 TO nRocks
  137.         IF r(r).live THEN drawRock r
  138.     NEXT
  139.     FOR i = 1 TO alienN
  140.         drawAliens i
  141.     NEXT
  142.     _FONT fnt2
  143.     s$ = "Asteroids AS-Space-KL"
  144.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 60), s$
  145.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(hs$)) / 2, 140), hs$
  146.     s$ = "A = Left spin"
  147.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 220), s$
  148.     s$ = "S = Right Spin"
  149.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 300), s$
  150.     s$ = "Space = Hyper jump"
  151.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 380), s$
  152.     s$ = "K = Thrust"
  153.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 460), s$
  154.     s$ = "L = Fire!"
  155.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 540), s$
  156.     _FONT fnt
  157.     k$ = INKEY$
  158.  
  159.     _DISPLAY
  160.     _LIMIT 60
  161.  
  162. restart:
  163. IF _FILEEXISTS("Asteroids High Score.txt") THEN
  164.     OPEN "Asteroids High Score.txt" FOR INPUT AS #1
  165.     INPUT #1, HS
  166.     CLOSE #1
  167. hs$ = "  High Score:" + STR$(HS)
  168. lives = 10: alienN = 1: rocks = 1: ' always active rocks
  169. points = 0: hits = 0: bullets = 0
  170. WHILE lives > 0 AND _KEYDOWN(27) = 0 ' init start restart
  171.     REDIM aliens(1 TO alienN) AS alienType
  172.     FOR ai = 1 TO alienN
  173.         newAlien ai
  174.     NEXT
  175.     FOR i = 1 TO nRocks 'reset rocks mainly clear baby rocks
  176.         newRock (i)
  177.         IF i > rocks THEN r(i).live = 0
  178.     NEXT
  179.     ship.x = xmax / 2 'avoids explosions top left corner at start, dang still get some!
  180.     ship.y = ymax / 2
  181.     ship.angle = 0
  182.     ship.thrustAngle = 0
  183.     ship.speed = 0
  184.     ship.live = 1
  185.     WHILE ship.live AND _KEYDOWN(27) = 0
  186.  
  187.         'draw everything then process bullets
  188.         drawStars 1
  189.  
  190.         FOR ai = 1 TO alienN
  191.             drawAliens ai
  192.         NEXT
  193.         FOR i = 1 TO nRocks
  194.             IF r(i).live THEN drawRock i ' while drawing rocks the ship could be blown up
  195.             IF ((r(i).x - ship.x) ^ 2 + (r(i).y - ship.y) ^ 2) ^ .5 < r(i).r + 30 THEN 'rock collides with ship?
  196.                 FOR br = 1 TO 200 STEP 5
  197.                     CIRCLE ((ship.x + r(i).x) / 2, (ship.y + r(i).y) / 2), br, _RGB32(255 - br, 255 - 2 * br, 0)
  198.                 NEXT
  199.                 drawRock i
  200.                 drawship
  201.                 ship.live = 0
  202.                 IF i <= rocks THEN newRock i ELSE r(i).live = 0
  203.             END IF
  204.         NEXT
  205.         FOR i = 1 TO nRocks 'smoke up the place with rock debris fields still flying out from hit frames ago
  206.             IF r(i).explodeFrame THEN
  207.                 r(i).explodeFrame = r(i).explodeFrame + 1
  208.                 IF r(i).explodeFrame > .25 * r(i).r THEN
  209.                     r(i).explodeFrame = 0
  210.                     IF i <= rocks THEN newRock i ' now replace the rock
  211.                 ELSE
  212.                     explode r(i).x, r(i).y, r(i).r, r(i).explodeFrame
  213.                 END IF
  214.             END IF
  215.         NEXT
  216.         IF ship.live THEN
  217.             FOR ai = 1 TO alienN
  218.                 IF SQR((aliens(ai).x - ship.x) ^ 2 + (aliens(ai).y - ship.y) ^ 2) < 60 THEN 'aliens and ship collisde boom boom
  219.                     FOR br = 1 TO 200 STEP 5
  220.                         CIRCLE ((ship.x + aliens(ai).x) / 2, (ship.y + aliens(ai).y) / 2), br, _RGB32(255 - br, 255 - 2 * br, 0)
  221.                     NEXT
  222.                     drawship
  223.                     ship.live = 0
  224.                     _CONTINUE
  225.                 ELSE
  226.                     drawship
  227.                 END IF
  228.             NEXT
  229.  
  230.             ' ship update
  231.             ship.thruster = 0 ' reset
  232.  
  233.             k$ = INKEY$
  234.             IF _KEYDOWN(ASC("a")) THEN ship.angle = ship.angle - pi / 90: ship.thruster = 4
  235.             IF _KEYDOWN(ASC("s")) THEN ship.angle = ship.angle + pi / 90: ship.thruster = 3
  236.             IF k$ = "k" THEN ship.speed = ship.speed + 3: ship.thrustAngle = ship.angle: ship.thruster = 1
  237.             IF k$ = "l" THEN 'l =fire
  238.                 fire = 0
  239.                 t = TIMER(.01)
  240.                 IF lastt = 0 OR t - lastt > .1 THEN fire = 1: lastt = t
  241.             END IF
  242.             IF _KEYHIT = 32 THEN 'hyperspace
  243.                 RANDOMIZE TIMER
  244.                 ship.x = (1000 * RND) + 100: ship.y = (500 * RND) + 100: ship.speed = 0
  245.             END IF
  246.  
  247.             '-----------------------------------------------
  248.             'locate ship
  249.             ship.x = ship.x + ship.speed * COS(ship.thrustAngle)
  250.             ship.y = ship.y + ship.speed * SIN(ship.thrustAngle)
  251.             ship.speed = ship.speed - .02
  252.             IF ship.speed < 0 THEN ship.speed = 0
  253.             IF ship.x < 0 THEN ship.x = xmax - ABS(ship.x)
  254.             IF ship.x > xmax THEN ship.x = ship.x - xmax
  255.             IF ship.y < 0 THEN ship.y = ymax - ABS(ship.y)
  256.             IF ship.y > ymax THEN ship.y = ship.y - ymax
  257.  
  258.  
  259.             FOR i = 0 TO nBullets 'handle bullets
  260.                 IF b(i).live = 0 AND fire = 1 THEN 'have inactive bullet to use
  261.                     b(i).x = ship.x + bSpeed * COS(ship.angle)
  262.                     b(i).y = ship.y + bSpeed * SIN(ship.angle)
  263.                     b(i).dx = bSpeed * COS(ship.angle)
  264.                     b(i).dy = bSpeed * SIN(ship.angle)
  265.                     b(i).live = -1
  266.                     bullets = bullets + 1
  267.                     fire = 0
  268.                 END IF
  269.                 IF b(i).live THEN 'new location
  270.                     b(i).x = b(i).x + b(i).dx
  271.                     b(i).y = b(i).y + b(i).dy
  272.                     IF b(i).x > 0 AND b(i).x < xmax AND b(i).y > 0 AND b(i).y < ymax THEN 'in bounds draw it
  273.  
  274.                         'bullet hit aliens?
  275.                         FOR ai = 1 TO alienN
  276.                             IF SQR((aliens(ai).x - b(i).x) ^ 2 + (aliens(ai).y - b(i).y) ^ 2) < 30 THEN
  277.                                 FOR br = 1 TO 120
  278.                                     CIRCLE (aliens(ai).x, aliens(ai).y), br / 3, plasma~&(0)
  279.                                 NEXT
  280.                                 _DISPLAY
  281.                                 _DELAY .05
  282.                                 hits = hits + 1
  283.                                 points = points + 100
  284.                                 aliens(ai).live = 0
  285.                                 newAlien ai
  286.                                 b(i).live = 0
  287.                                 _CONTINUE
  288.                             END IF
  289.                         NEXT
  290.                         FOR r = 1 TO nRocks 'check for collision with rock
  291.                             IF r(r).live THEN
  292.                                 IF SQR((r(r).x - b(i).x) ^ 2 + (r(r).y - b(i).y) ^ 2) < r(r).r THEN 'its a hit!
  293.                                     r(r).explodeFrame = 1 'linger with explosion
  294.                                     r(r).live = 0
  295.                                     hits = hits + 1
  296.                                     points = points + ((r(r).speed - .5) * 50 + (90 - (r(r).r - 10)) * 1.1111) / 2
  297.                                     IF r(r).r > 30 THEN '       split rock  into ? new ones
  298.                                         maxBabyRocks = INT((r(r).r - 10) / 10)
  299.                                         maxBabyRocks = irnd&(2, maxBabyRocks) ' pick a number of baby Rocks
  300.                                         FOR br = 1 TO maxBabyRocks
  301.                                             '                        new rock
  302.                                             newRockN = freeRock& '                          get inactive rock number
  303.                                             newRock newRockN '                              new identity and activate
  304.                                             r(newRockN).r = (r(r).r - 10) / maxBabyRocks '  split in equal parts minus 20% mass
  305.                                             r(newRockN).x = r(r).x + irnd&(-30, 30) '       thrown from parent
  306.                                             r(newRockN).y = r(r).y + irnd&(-30, 30)
  307.                                             r(newRockN).c = r(r).c '                   same color as parent
  308.                                             r(newRockN).heading = rrnd(ship.angle - .75 * pi, ship.angle + .75 * pi)
  309.                                         NEXT
  310.                                     END IF ' big enough to split
  311.                                     b(i).live = 0 'kill bullet
  312.                                 END IF ' hit rock
  313.                             END IF 'rock is there
  314.                         NEXT ' rock
  315.                         IF b(i).live THEN fcirc b(i).x, b(i).y, 3, _RGB32(255, 255, 0) 'draws bullet
  316.                     ELSE
  317.                         b(i).live = 0 'out of bounds
  318.                     END IF ' bullet is in bounds
  319.                 END IF ' bullet live
  320.             NEXT ' bullet
  321.         END IF ' if ship still live
  322.         _DISPLAY
  323.         IF ship.live = 0 THEN
  324.             lives = lives - 1
  325.             IF lives MOD 4 = 0 THEN rocks = rocks + 1
  326.             IF lives MOD 4 = 2 THEN alienN = alienN + 1
  327.             s$ = "Lives:" + STR$(lives) + "  Hits:" + STR$(hits) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits * 100 / bullets)) + "%"
  328.             _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 80), s$
  329.             _FONT fnt2
  330.             s$ = STR$(points) + hs$
  331.             _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  332.             _FONT fnt
  333.             s$ = "Press Enter to enter your next life"
  334.             _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 + 120), s$
  335.             _DISPLAY
  336.             _MOUSESHOW
  337.             WHILE _KEYDOWN(13) = 0: WEND 'wait for enter key
  338.         ELSE
  339.             _LIMIT 30 ' if ship dies let's rest and regroup  before restart next life
  340.         END IF
  341.     WEND
  342.     _DISPLAY
  343. IF points > HS THEN
  344.     OPEN "Asteroids High Score.txt" FOR OUTPUT AS #1
  345.     PRINT #1, points
  346.     CLOSE #1
  347. ship.x = -200: ship.y = -200 'get it out of the way
  348. i = 0
  349.     drawStars 0
  350.     i = i + 1
  351.     IF i MOD 30 = 29 AND rocks < nRocks THEN rocks = rocks + 1: r(rocks).live = 1
  352.     FOR r = 1 TO nRocks
  353.         IF r(r).live THEN drawRock r
  354.     NEXT
  355.     s$ = "Lives:" + STR$(lives) + "  Hits:" + STR$(hits) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits * 100 / bullets)) + "%"
  356.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 80), s$
  357.     _FONT fnt2
  358.     s$ = STR$(points)
  359.     IF points > HS THEN s$ = s$ + " a New Record!" ELSE s$ = STR$(points) + hs$
  360.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  361.     _FONT fnt
  362.     s$ = "Press q to quit, p or a to Play Again..."
  363.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 + 120), s$
  364.     IF _KEYDOWN(ASC("a")) OR _KEYDOWN(ASC("p")) THEN GOTO restart
  365.     _DISPLAY
  366.     _LIMIT 60
  367.  
  368. SUB drawStars (moving)
  369.     TYPE starType
  370.         x AS SINGLE
  371.         y AS SINGLE
  372.         size AS SINGLE
  373.         c AS INTEGER
  374.     END TYPE
  375.     STATIC beenHere, stars(600) AS starType, cy AS LONG
  376.     DIM i AS LONG
  377.     IF beenHere = 0 THEN 'static part
  378.         FOR i = 0 TO 200
  379.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = 0
  380.             stars(i).c = irnd&(80, 140)
  381.         NEXT
  382.         FOR i = 0 TO 200
  383.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = .3
  384.             stars(i).c = irnd&(80, 140)
  385.         NEXT
  386.  
  387.         FOR i = 1 TO 140
  388.             stars(i + 400).x = RND * xmax: stars(i + 400).y = RND * ymax: stars(i + 100).size = .6
  389.             stars(i).c = irnd&(110, 170)
  390.         NEXT
  391.         FOR i = 1 TO 50
  392.             stars(i + 540).x = RND * xmax: stars(i + 540).y = RND * ymax: stars(i + 170).size = 1.2
  393.             stars(i).c = irnd&(140, 200)
  394.         NEXT
  395.         FOR i = 1 TO 10
  396.             stars(i + 590).x = RND * xmax: stars(i + 590).y = RND * ymax: stars(i + 195).size = 2.4
  397.             stars(i).c = irnd&(170, 235)
  398.         NEXT
  399.         cy = ymax / 2
  400.         beenHere = 1
  401.     END IF
  402.     FOR i = 0 TO cy
  403.         LINE (0, i)-(xmax, i), _RGB32(0, 0, .1 * i + 4)
  404.         LINE (0, ymax - i)-(xmax, ymax - i), _RGB(0, 0, .1 * i + 4)
  405.     NEXT
  406.     FOR i = 0 TO 200
  407.         IF moving THEN
  408.             stars(i).x = stars(i).x + .2 * stars(i).size ^ stars(i).size
  409.             IF stars(i).x > xmax THEN stars(i).x = -1 * RND * 20
  410.         END IF
  411.         fcirc stars(i).x, stars(i).y, stars(i).size, _RGB32(stars(i).c - 10, stars(i).c, stars(i).c + 10)
  412.     NEXT
  413.  
  414. SUB newAlien (i AS LONG)
  415.     DIM side AS LONG, heading
  416.     RANDOMIZE TIMER * RND 'to avoid making twins
  417.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  418.     aliens(i).fireX = irnd(10, xmax - 10)
  419.     aliens(i).fireY = irnd(10, ymax - 10)
  420.     aliens(i).attackFrame = irnd(30, 400) ' EDIT a tweak to survive a little long before getting murdered with low lives over and over...
  421.     SELECT CASE side
  422.         CASE 1
  423.             aliens(i).x = -10
  424.             aliens(i).y = rrnd(20, ymax - 20)
  425.         CASE 2
  426.             aliens(i).x = xmax + 10
  427.             aliens(i).y = rrnd(20, ymax - 20)
  428.         CASE 3
  429.             aliens(i).x = rrnd(20, xmax - 20)
  430.             aliens(i).y = -10
  431.         CASE 4
  432.             aliens(i).x = rrnd(20, xmax - 20)
  433.             aliens(i).y = ymax + 10
  434.     END SELECT
  435.     heading = _ATAN2(aliens(i).fireY - aliens(i).y, aliens(i).fireX - aliens(i).x)
  436.     aliens(i).dx = .5 * COS(heading)
  437.     aliens(i).dy = .5 * SIN(heading)
  438.     aliens(i).live = 0
  439.     aliens(i).transform = 0
  440.     aliens(i).c = _RGB32(irnd(128, 255), irnd(0, 255), irnd(0, 255))
  441.  
  442. FUNCTION plasma~& (new AS LONG)
  443.     STATIC r, g, b, cnt, beenHere
  444.     IF beenHere = 0 OR new THEN
  445.         r = RND: g = RND: b = RND: beenHere = 1: cnt = 0
  446.     END IF
  447.     cnt = cnt + .2
  448.     plasma~& = _RGB32(127 + 127 * SIN(r * cnt), 127 + 127 * SIN(g * cnt), 127 + 127 * SIN(b * cnt))
  449.  
  450. SUB drawAliens (i AS LONG) 'shipType
  451.     DIM light AS LONG, heading, r AS LONG, g AS LONG, b AS LONG
  452.     IF aliens(i).live THEN
  453.         IF aliens(i).transform = 0 THEN
  454.             r = _RED32(aliens(i).c): g = _GREEN32(aliens(i).c): b = _BLUE32(aliens(i).c)
  455.             fellipse aliens(i).x, aliens(i).y, 6, 15, _RGB32(r, g - 120, b - 100)
  456.             fellipse aliens(i).x, aliens(i).y, 18, 11, _RGB32(r, g - 60, b - 50)
  457.             fellipse aliens(i).x, aliens(i).y, 30, 7, _RGB32(r, g, b)
  458.             FOR light = 0 TO 5
  459.                 fcirc aliens(i).x - 30 + 11 * light + aliens(i).ls, aliens(i).y, 1, _RGB32(aliens(i).ls * 50, aliens(i).ls * 50, aliens(i).ls * 50)
  460.             NEXT
  461.             aliens(i).ls = aliens(i).ls + 1
  462.             IF aliens(i).ls > 5 THEN aliens(i).ls = 0
  463.         ELSE
  464.             drawBall aliens(i).x, aliens(i).y, 30, aliens(i).c
  465.         END IF
  466.         'time to shoot?
  467.         aliens(i).x = aliens(i).x + aliens(i).dx
  468.         aliens(i).y = aliens(i).y + aliens(i).dy
  469.         IF SQR((aliens(i).fireX - aliens(i).x) ^ 2 + (aliens(i).fireY - aliens(i).y) ^ 2) < 5 THEN 'transform into the bolder of death
  470.             aliens(i).transform = 1
  471.             heading = _ATAN2(ship.y - aliens(i).y, ship.x - aliens(i).x)
  472.             aliens(i).dx = 2.5 * COS(heading)
  473.             aliens(i).dy = 2.5 * SIN(heading)
  474.         END IF
  475.         IF aliens(i).x < -10 OR aliens(i).x > xmax + 10 THEN
  476.             IF aliens(i).y < -10 OR aliens(i).y > ymax + 10 THEN '  out of bounds goodbye bolder of death!
  477.                 aliens(i).live = 0 'man we dodged a bullet here!!!!
  478.                 newAlien i 'reset the trap
  479.             END IF
  480.         END IF
  481.     ELSE
  482.         IF aliens(i).attackFrame THEN
  483.             aliens(i).attackFrame = aliens(i).attackFrame - 1
  484.             IF aliens(i).attackFrame = 0 THEN
  485.                 aliens(i).live = 1
  486.             END IF
  487.         END IF
  488.     END IF
  489.  
  490. FUNCTION freeRock&
  491.     DIM i AS LONG
  492.     FOR i = rocks + 1 TO nRocks ' look for inactive rock number
  493.         IF r(i).live = 0 AND r(i).explodeFrame = 0 THEN freeRock& = i: EXIT FUNCTION
  494.     NEXT
  495.  
  496. SUB explode (x AS LONG, y AS LONG, r AS LONG, frm AS LONG)
  497.     DIM maxParticles AS LONG, i AS LONG, rounds AS LONG, loopCount AS LONG
  498.     maxParticles = r * 4
  499.     FOR i = 1 TO r
  500.         NewDot i, x, y, r
  501.     NEXT
  502.     rounds = r
  503.     FOR loopCount = 0 TO frm
  504.         IF _KEYDOWN(27) THEN END
  505.         FOR i = 1 TO rounds
  506.             dots(i).x = dots(i).x + dots(i).dx
  507.             dots(i).y = dots(i).y + dots(i).dy
  508.             fcirc dots(i).x, dots(i).y, dots(i).size, dots(i).kolor
  509.         NEXT
  510.         IF rounds < maxParticles THEN
  511.             FOR i = 1 TO r
  512.                 NewDot (rounds + i), x, y, r
  513.             NEXT
  514.             rounds = rounds + r
  515.         END IF
  516.     NEXT
  517.  
  518. SUB NewDot (i AS LONG, x AS LONG, y AS LONG, r AS LONG)
  519.     DIM angle, rd
  520.     angle = pi * 2 * RND
  521.     rd = RND * 30
  522.     dots(i).x = x + rd * COS(angle)
  523.     dots(i).y = y + rd * SIN(angle)
  524.     dots(i).size = RND * r * .05
  525.     rd = RND 'STxAxTIC recommended for rounder spreads
  526.     dots(i).dx = rd * 10 * (10 - 2 * dots(i).size) * COS(angle)
  527.     dots(i).dy = rd * 10 * (10 - 2 * dots(i).size) * SIN(angle)
  528.     rd = 20 + RND * 70
  529.     dots(i).kolor = _RGBA32(rd, rd, rd, 80)
  530.  
  531. SUB drawship 'simple red iso triangle pointed towards radianAngle
  532.     DIM x1 AS LONG, y1 AS LONG, x2 AS LONG, y2 AS LONG, x3 AS LONG, y3 AS LONG
  533.     DIM x4 AS LONG, y4 AS LONG, x5 AS LONG, y5 AS LONG, x6 AS LONG, y6 AS LONG
  534.     DIM x7 AS LONG, y7 AS LONG
  535.  
  536.  
  537.     'calculate 3 points of triangle ship
  538.     fcirc ship.x, ship.y, 30, &H05FFFFFF
  539.     x1 = ship.x + 30 * COS(ship.angle) ' front point
  540.     y1 = ship.y + 30 * SIN(ship.angle) '
  541.     x2 = ship.x + 30 * COS(ship.angle + .6666 * pi) ' wing
  542.     y2 = ship.y + 30 * SIN(ship.angle + .6666 * pi)
  543.     x3 = ship.x + 30 * COS(ship.angle - .6666 * pi) ' other wing
  544.     y3 = ship.y + 30 * SIN(ship.angle - .6666 * pi)
  545.     ftri ship.x, ship.y, x1, y1, x2, y2, _RGB32(80, 120, 80, 80)
  546.     ftri ship.x, ship.y, x1, y1, x3, y3, _RGB32(60, 100, 60, 80)
  547.     LINE (x1, y1)-(ship.x, ship.y), _RGB32(255, 255, 128)
  548.     LINE (x1, y1)-(x2, y2), _RGB32(180, 180, 120)
  549.     LINE (x1, y1)-(x3, y3), _RGB32(180, 180, 120)
  550.  
  551.     SELECT CASE ship.thruster
  552.         CASE 1 'forward apex = ship.x, ship,y  direction = ship.angle + pi
  553.             x4 = ship.x + 25 * COS(ship.angle - 17 / 18 * pi)
  554.             y4 = ship.y + 25 * SIN(ship.angle - 17 / 18 * pi)
  555.             x5 = ship.x + 25 * COS(ship.angle - 19 / 18 * pi)
  556.             y5 = ship.y + 25 * SIN(ship.angle - 19 / 18 * pi)
  557.             ftri ship.x, ship.y, x4, y4, x5, y5, &H99FFFF88
  558.         CASE 2 'reverse apex = x1, y1
  559.             x6 = x2 + 25 * COS(ship.angle + 1 / 18 * pi)
  560.             y6 = y2 + 25 * SIN(ship.angle + 1 / 18 * pi)
  561.             x7 = x2 + 25 * COS(ship.angle - 1 / 18 * pi)
  562.             y7 = y2 + 25 * SIN(ship.angle - 1 / 18 * pi)
  563.             ftri x2, y2, x6, y6, x7, y7, &H99FFFF88
  564.  
  565.             x6 = x3 + 25 * COS(ship.angle + 1 / 18 * pi)
  566.             y6 = y3 + 25 * SIN(ship.angle + 1 / 18 * pi)
  567.             x7 = x3 + 25 * COS(ship.angle - 1 / 18 * pi)
  568.             y7 = y3 + 25 * SIN(ship.angle - 1 / 18 * pi)
  569.             ftri x3, y3, x6, y6, x7, y7, &H99FFFF88
  570.         CASE 3 'left apex = x2, y2
  571.             x6 = x3 + 25 * COS(ship.angle - 17 / 18 * pi)
  572.             y6 = y3 + 25 * SIN(ship.angle - 17 / 18 * pi)
  573.             x7 = x3 + 25 * COS(ship.angle - 19 / 18 * pi)
  574.             y7 = y3 + 25 * SIN(ship.angle - 19 / 18 * pi)
  575.             ftri x3, y3, x6, y6, x7, y7, &H99FFFF88
  576.  
  577.             'x6 = x2 + 25 * COS(ship.angle + 1 / 18 * pi)
  578.             'y6 = y2 + 25 * SIN(ship.angle + 1 / 18 * pi)
  579.             'x7 = x2 + 25 * COS(ship.angle - 1 / 18 * pi)
  580.             'y7 = y2 + 25 * SIN(ship.angle - 1 / 18 * pi)
  581.             'ftri x2, y2, x6, y6, x7, y7, &H99FFFF88
  582.         CASE 4 'right
  583.             x6 = x2 + 25 * COS(ship.angle - 17 / 18 * pi)
  584.             y6 = y2 + 25 * SIN(ship.angle - 17 / 18 * pi)
  585.             x7 = x2 + 25 * COS(ship.angle - 19 / 18 * pi)
  586.             y7 = y2 + 25 * SIN(ship.angle - 19 / 18 * pi)
  587.             ftri x2, y2, x6, y6, x7, y7, &H99FFFF88
  588.  
  589.             'x6 = x3 + 25 * COS(ship.angle + 1 / 18 * pi)
  590.             'y6 = y3 + 25 * SIN(ship.angle + 1 / 18 * pi)
  591.             'x7 = x3 + 25 * COS(ship.angle - 1 / 18 * pi)
  592.             'y7 = y3 + 25 * SIN(ship.angle - 1 / 18 * pi)
  593.             'ftri x3, y3, x6, y6, x7, y7, &H99FFFF88
  594.     END SELECT
  595.  
  596. SUB drawRock (iRock)
  597.     RANDOMIZE USING r(iRock).seed 'this prevents having to save a particular sequence of random number
  598.     DIM dx, dy, j AS LONG, rRad AS SINGLE, leg AS SINGLE, x0 AS LONG, y0 AS LONG, rc AS LONG, c~&, x1 AS LONG, y1 AS LONG, xoff, yoff, i AS LONG
  599.     DIM x2 AS LONG, y2 AS LONG
  600.     dx = r(iRock).speed * COS(r(iRock).heading)
  601.     dy = r(iRock).speed * SIN(r(iRock).heading) 'update location
  602.     r(iRock).ra = r(iRock).ra + r(iRock).spin
  603.     IF r(iRock).x + dx + r(iRock).r < 0 OR r(iRock).x + dx - r(iRock).r > xmax OR r(iRock).y + dy + r(iRock).r < 0 OR r(iRock).y + dy - r(iRock).r > ymax THEN
  604.         IF iRock <= rocks THEN newRock iRock ELSE r(iRock).live = 0
  605.         EXIT SUB ' reassigned get out of here
  606.     ELSE
  607.         r(iRock).x = r(iRock).x + dx
  608.         r(iRock).y = r(iRock).y + dy
  609.     END IF
  610.     FOR j = 10 TO 3 STEP -1 '                  rock drawing (see demo program where developed code)
  611.         rRad = .1 * j * r(iRock).r
  612.         leg = rRad * (RND * .7 + .3)
  613.         x0 = r(iRock).x + leg * COS(r(iRock).ra)
  614.         y0 = r(iRock).y + leg * SIN(r(iRock).ra)
  615.         rc = r(iRock).c + 30 * RND - 15
  616.         c~& = _RGB32(rc + 5, rc - 10, rc + 5)
  617.         x1 = x0
  618.         y1 = y0
  619.         xoff = RND * 20 - 10 + r(iRock).x
  620.         yoff = RND * 20 - 10 + r(iRock).y
  621.         FOR i = 1 TO 12
  622.             leg = rRad * (RND * .35 + .65)
  623.             IF i = 12 THEN
  624.                 x2 = x0: y2 = y0
  625.             ELSE
  626.                 x2 = xoff + leg * COS(i * polyAngle + r(iRock).ra)
  627.                 y2 = yoff + leg * SIN(i * polyAngle + r(iRock).ra)
  628.             END IF
  629.             ftri r(iRock).x, r(iRock).y, x1, y1, x2, y2, c~&
  630.             x1 = x2: y1 = y2
  631.         NEXT
  632.     NEXT
  633.  
  634. SUB newRock (iRock)
  635.     DIM side AS LONG
  636.     RANDOMIZE TIMER * RND 'to avoid making twins
  637.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  638.     SELECT CASE side
  639.         CASE 1
  640.             r(iRock).x = -100
  641.             r(iRock).y = rrnd(20, ymax - 20)
  642.             r(iRock).heading = 3 * pi / 2 + RND * pi
  643.         CASE 2
  644.             r(iRock).x = xmax + 100
  645.             r(iRock).y = rrnd(20, ymax - 20)
  646.             r(iRock).heading = pi / 2 + RND * pi
  647.         CASE 3
  648.             r(iRock).x = rrnd(20, xmax - 20)
  649.             r(iRock).y = -100
  650.             r(iRock).heading = RND * pi
  651.         CASE 4
  652.             r(iRock).x = rrnd(20, xmax - 20)
  653.             r(iRock).y = ymax + 100
  654.             r(iRock).heading = pi + RND * pi
  655.     END SELECT
  656.     r(iRock).speed = rrnd(.5, 2.5) 'speed, rotation angle, radius, gray coloring, spin, seed, hit for explosion
  657.     r(iRock).ra = RND * 2 * pi
  658.     r(iRock).r = irnd&(30, 100)
  659.     r(iRock).c = irnd&(60, 110) ' Ken request increase in rock color
  660.     r(iRock).spin = rrnd(-pi / 20, pi / 20)
  661.     r(iRock).seed = INT(RND * 64000) - 32000
  662.     r(iRock).explodeFrame = 0
  663.     r(iRock).live = 1
  664.  
  665. FUNCTION irnd& (n1, n2) 'return an integer between 2 numbers
  666.     DIM l%, h%
  667.     IF n1 > n2 THEN l% = n2: h% = n1 ELSE l% = n1: h% = n2
  668.     irnd& = INT(RND * (h% - l% + 1)) + l%
  669.  
  670. FUNCTION rrnd (n1, n2) ' return number (expecting reals =_single, double, _float depending on default / define setup)
  671.     rrnd = (n2 - n1) * RND + n1
  672.  
  673. SUB drawBall (x, y, r, c AS _UNSIGNED LONG)
  674.     DIM red AS LONG, grn AS LONG, blu AS LONG, rr AS LONG, f
  675.     red = _RED32(c): grn = _GREEN32(c): blu = _BLUE32(c)
  676.     FOR rr = r TO 0 STEP -1
  677.         f = 1 - rr / r
  678.         fcirc x, y, rr, _RGB32(red * f, grn * f, blu * f)
  679.     NEXT
  680.  
  681. SUB fellipse (CX AS LONG, CY AS LONG, xr AS LONG, yr AS LONG, C AS _UNSIGNED LONG)
  682.     IF xr = 0 OR yr = 0 THEN EXIT SUB
  683.     DIM x AS LONG, y AS LONG
  684.     w2 = xr * xr: h2 = yr * yr: h2w2 = h2 * w2
  685.     LINE (CX - xr, CY)-(CX + xr, CY), C, BF
  686.     DO WHILE y < yr
  687.         y = y + 1
  688.         x = SQR((h2w2 - y * y * w2) \ h2)
  689.         LINE (CX - x, CY + y)-(CX + x, CY + y), C, BF
  690.         LINE (CX - x, CY - y)-(CX + x, CY - y), C, BF
  691.     LOOP
  692.  
  693. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  694.     DIM D AS LONG
  695.     STATIC a&
  696.     D = _DEST
  697.     IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32)
  698.     _DEST a&
  699.     _DONTBLEND a& '  '<<<< new 2019-12-16 fix
  700.     PSET (0, 0), K
  701.     _BLEND a& '<<<< new 2019-12-16 fix
  702.     _DEST D
  703.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  704.  
  705. SUB fcirc (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG) 'vince version
  706.     DIM x0 AS LONG, y0 AS LONG, e AS LONG
  707.     x0 = R: y0 = 0: e = 0
  708.     DO WHILE y0 < x0
  709.         IF e <= 0 THEN
  710.             y0 = y0 + 1
  711.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  712.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  713.             e = e + 2 * y0
  714.         ELSE
  715.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  716.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  717.             x0 = x0 - 1: e = e - 2 * x0
  718.         END IF
  719.     LOOP
  720.     LINE (x - R, y)-(x + R, y), C, BF
  721.  
« Last Edit: November 04, 2020, 02:37:06 pm by SierraKen »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #65 on: November 04, 2020, 03:31:12 pm »
Quote
Here you go B+. :) You will hate me when I tell you how I fixed it. It's something you guys have told me not to use more than once in an entire program but it works. I added RANDOMIZE TIMER right before the RND lines. I also changed the INKEY$ to KEYHIT since it seemed to work better, but you can try INKEY$ again if you want. What I found out was that it was actually working every time with KEYHIT (and possibly INKEY$) but it was just going to the same location you started at. For example, if I moved and used it, it went back to where it was before, almost every time. So that meant it was a randomize problem so RANDOMIZE TIMER does the trick. :) For some reason it needed to randomize the timer again probably since it also uses RND in other locations in your program. Oh, as I experimented with different things I also removed XMAX and YMAX and just used your values of it instead to make it easier on the program. That probably doesn't do anything though but I left it there.

@SierraKen

Brilliant! Thankyou, thankyou, thankyou!

I know exactly why you have to RANDOMIZE TIMER because I use RANDOMIZE USING with a seed number to redraw rocks over and over. It is a clever way to save a bunch of random data without saving it, just use same seed number in the same sequence of code. I got caught by that once before.

Yep, so there is at least one occasion when RANDOMIZE TIMER before using RND makes sense.

So you have saved me allot grief today when I install the rest of the controls, one shining gold star for you!

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: b+ Asteroids makeover
« Reply #66 on: November 04, 2020, 04:34:15 pm »
Suggestion: If the overall "field of view" were larger than the screen image then a 'mini-map' could be added. Resolution of the mini-map could be linked to player health. eg: Full health will show all large and small rocks and ufo's. Poor health only large objects.

Just a thought...

J
Logic is the beginning of wisdom.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #67 on: November 04, 2020, 05:07:06 pm »
Thanks @johnno56

I will put your idea on back burner while I try to get Asteroids playing the way I think it should. It may be a proper pilot that we might be waiting for. :)

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: b+ Asteroids makeover
« Reply #68 on: November 04, 2020, 06:14:27 pm »
You're welcome B+, glad I could help. :)

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #69 on: November 04, 2020, 11:05:35 pm »
OK here is M9 with the new Thrust control and engine installed, this is working nice! Hyperspace jump handy and you can thrust through one border and come out the other side. Just shoot like a maniac!

Code: QB64: [Select]
  1. _TITLE "b+ Asteroids m9 AS-Space-KL " 'started 2018-07-13
  2. '2020 - Oct and Nov: Special thanks to SierraKen who has been helpful with suggestions, ideas and fixes.
  3.  
  4. ' Far far away in a universe where Newton's 1st Law of Motion is not obeyed...    ;-))
  5.  
  6.  
  7. '                                            New Controls
  8. ' key a = turn left
  9. ' key s = turn right
  10. '          spacebar =  "hyperspace" show up somewhere else  better or worse use when collision is imminent
  11. ' key k = thrust  just a burst in direction you are pointed but doesn't last
  12. ' key l = fire! owwha, owha, owha...
  13.  
  14. '=================================================================================================================
  15.  
  16. ' 2020-10-27 remove the alternate subs and get down below 200 LOC almost there now! new shooter action font and background
  17. ' 2020-10-28 another makeover explosions and split asteroids
  18. ' 2020-10-29 fix baby rock management, break between lives
  19. ' 2020-10-29 fix left/right gun, fix explosions over many frames to eliminate pause in action, speed up 60 fps
  20. ' 2020-10-30 m3 SierraKen's idea to angle shooter with mousewheel also finish WASD options, more rocks, points system
  21. ' points:
  22. ' The higher the speed the better    speed range .5 to 2.5, diff = 2 * 50 = 100          s - .5 * 50
  23. ' DELETE The lower the color the better   color range 10 to 60, diff =      50 * 2 = 100  50 - (c - 10) * 2
  24. ' The smaller the size the better  size range 10 to 100, diff = 90 * 1.1111 = 100  90 - (sz -10) * 1.1111
  25. '        ((speed - .5) * 50 + (90 - (r - 10)) * 1.1111) / 2 = 100 best score per hit
  26. ' 2020-10-30 increase level of difficulty, fix double lives lost, add an ending after all lives spent.
  27. ' 2020-10-31 M4 They are Here - the aliens have accepted my invitaion for war games don't get caught in their beam.
  28. ' rework ending and variable LONG suffix. Aliens on the attack 100 points before or after transformed into the Bolder of Death.
  29. ' 2020-11-01 M5 FX Moving through space, Oh yeah, more aliens!
  30. ' 2020-11-01 M6 add play again and save high game , continuous shoot
  31. ' 2020-11-01 M7 fix hits count when hit alien ship or Bolder of Death. Fix lights on aliens ship. I want to see collsions with ship.
  32. ' Ken recommends removing text in middle of screen, yeah, distracting. Makeover ship as with mouse x, y it's center. Add Splash screen.
  33. ' Show mouse in between lives so can be in screen center when press key to start next run.
  34.  
  35. ' 2020-11-03 M9 watching videos on Asteroids, I found a view and description of the control panel, it is:
  36. ' 2 buttons on left and lower button in middle and 2 buttons on right level with 2 on left.
  37. ' 2 buttons on left are left and right turns they will be Keys A and S
  38. ' The middle will be spacebar for Hypespace or these days we might call it worm hole, jump to another location better or worse!
  39. ' 2 buttons on right K and L: K will be a thruster of sorts you eventually come to a stop (not what Newton would like) L is the fire button.
  40. ' So let's try that. I am impressed by hitting thruster and shooting all around as you dift in direction gun was pointed when hit thruster.
  41. ' Lighten rocks and change points, based now only on size and speed of Asteroids.
  42. ' 2020-11-04 M9 Install new update to thrust control. Thanks to SierraKen for finding out what happened to Hyperspace jump when press
  43. ' spacebar a 2nd time in a life. Oh also Boulders of Death are now more like smooth colored spheres. Ahhhh Fixed the crashing at the borders
  44. ' now fly out one side and come back in on the other! This is getting good! Adding some sound effects.
  45.  
  46. '================================================================================================================
  47.  
  48. '    NOTE: !!!!!!!!!!!!!!!   When there is a pause in action, just press enter,  as in enter a new life!
  49.  
  50. '================================================================================================================
  51.  
  52. CONST xmax = 1200, ymax = 700, pi = _PI, polyAngle = _PI / 6, nRocks = 300, nBullets = 2000, bSpeed = 15
  53.  
  54. TYPE alienType
  55.     x AS SINGLE
  56.     y AS SINGLE
  57.     dx AS SINGLE
  58.     dy AS SINGLE
  59.     ls AS LONG ' lights offset and gray scale
  60.     c AS _UNSIGNED LONG ' color
  61.     live AS LONG
  62.     attackFrame AS LONG
  63.     fireX AS SINGLE
  64.     fireY AS SINGLE
  65.     transform AS LONG
  66.  
  67. TYPE particle
  68.     x AS SINGLE
  69.     y AS SINGLE
  70.     dx AS SINGLE
  71.     dy AS SINGLE
  72.     size AS SINGLE
  73.     kolor AS _UNSIGNED LONG
  74.  
  75. TYPE bullet
  76.     x AS SINGLE
  77.     y AS SINGLE
  78.     dx AS SINGLE
  79.     dy AS SINGLE
  80.     live AS LONG
  81.  
  82. TYPE shipType
  83.     x AS SINGLE
  84.     y AS SINGLE
  85.     live AS LONG
  86.     speed AS SINGLE '       just a constant now when Thrust is applied
  87.     thrustAngle AS SINGLE ' ship/gun angle at moment Thrust is pressed
  88.     angle AS SINGLE '       rotated position ship/gun now A or S keypress or hold down
  89.     thrust AS LONG '        this now tracks how many frames ship will move at speed and thrustAngle
  90.  
  91. TYPE rock
  92.     x AS SINGLE
  93.     y AS SINGLE
  94.     r AS LONG '            radius
  95.     ra AS SINGLE '         rotation position   a = a + spin
  96.     heading AS SINGLE '    heading from which dx, dy are calc with speed
  97.     speed AS SINGLE '      speed
  98.     spin AS SINGLE '       rotation direction and amount
  99.     seed AS LONG '         for drawing rocks with RND USING
  100.     c AS LONG '            color   rgb(c, c, c)
  101.     live AS LONG '         need this to track rocks still active like bullets
  102.     explodeFrame AS LONG ' after a rock is hit by bullet, it explodes and in more than one frame
  103.  
  104. REDIM SHARED aliens(1 TO 5) AS alienType
  105. DIM SHARED dots(2000) AS particle ' explosions
  106. DIM SHARED b(nBullets) AS bullet
  107. DIM SHARED ship AS shipType
  108. DIM SHARED r(nRocks) AS rock
  109. DIM SHARED points AS LONG
  110. DIM SHARED rocks AS LONG 'rocks is the minimum number of parent rocks to have on screen  automatic replace when hit or out of bounds
  111.  
  112. DIM HS AS LONG, fnt AS LONG, fnt2 AS LONG ' file LOAD handles
  113. DIM i AS LONG, bullets AS LONG, fire AS LONG ' index and bullets
  114. DIM r AS LONG, newRockN AS LONG, maxBabyRocks AS LONG, br AS LONG, hits AS LONG ' rock stuff
  115. DIM ai AS LONG, alienN AS LONG ' alien index and number
  116. DIM kh AS LONG 'key hit for ship thruster k or hyperspace jump spacebar
  117. DIM hs$, s$, k$, t, lastt 'high score, general string and times for bullets
  118. ship.speed = 3.5 'this would be a constant but ship has to declared as Ship Type first
  119.  
  120. SCREEN _NEWIMAGE(xmax, ymax, 32)
  121. _SCREENMOVE 100, 20
  122.  
  123. fnt = _LOADFONT("ARLRDBD.ttf", 16, "MONOSPACE")
  124. fnt2 = _LOADFONT("ARLRDBD.ttf", 40, "MONOSPACE")
  125. _FONT fnt2
  126. COLOR &HFF00FFFF, &H00000000
  127.  
  128. IF _FILEEXISTS("Asteroids High Score.txt") THEN
  129.     OPEN "Asteroids High Score.txt" FOR INPUT AS #1
  130.     INPUT #1, HS
  131.     CLOSE #1
  132. hs$ = "High Score:" + STR$(HS)
  133.  
  134. 'a little splash screen
  135. rocks = 7: alienN = 3
  136. FOR i = 1 TO nRocks
  137.     newRock i
  138.     IF i > rocks THEN r(i).live = 0
  139. FOR i = 1 TO alienN
  140.     newAlien i
  141. i = 0
  142.     drawStars 0
  143.     i = i + 1
  144.     IF i MOD 30 = 29 AND rocks < nRocks THEN rocks = rocks + 1: r(rocks).live = 1
  145.     FOR r = 1 TO nRocks
  146.         IF r(r).live THEN drawRock r
  147.     NEXT
  148.     FOR i = 1 TO alienN
  149.         drawAliens i
  150.     NEXT
  151.     _FONT fnt2
  152.     s$ = "Asteroids AS-Space-KL"
  153.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 60), s$
  154.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(hs$)) / 2, 140), hs$
  155.     s$ = "A = Left spin"
  156.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 220), s$
  157.     s$ = "S = Right Spin"
  158.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 300), s$
  159.     s$ = "Space = Hyper jump"
  160.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 380), s$
  161.     s$ = "K = Thrust"
  162.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 460), s$
  163.     s$ = "L = Fire!"
  164.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 540), s$
  165.     _FONT fnt
  166.     k$ = INKEY$
  167.     _DISPLAY
  168.     _LIMIT 60
  169.  
  170. restart:
  171. IF _FILEEXISTS("Asteroids High Score.txt") THEN
  172.     OPEN "Asteroids High Score.txt" FOR INPUT AS #1
  173.     INPUT #1, HS
  174.     CLOSE #1
  175. hs$ = "  High Score:" + STR$(HS)
  176. lives = 10: alienN = 1: rocks = 1: ' always active rocks
  177. points = 0: hits = 0: bullets = 0
  178. WHILE lives > 0 AND _KEYDOWN(27) = 0 ' init start restart
  179.     REDIM aliens(1 TO alienN) AS alienType
  180.     FOR ai = 1 TO alienN
  181.         newAlien ai
  182.     NEXT
  183.     FOR i = 1 TO nRocks 'reset rocks mainly clear baby rocks
  184.         newRock (i)
  185.         IF i > rocks THEN r(i).live = 0
  186.     NEXT
  187.     ship.x = xmax / 2 'avoids explosions top left corner at start, dang still get some!
  188.     ship.y = ymax / 2
  189.     ship.angle = 0
  190.     ship.thrustAngle = 0
  191.     ship.thrust = 0
  192.     ship.live = 1
  193.     WHILE ship.live AND _KEYDOWN(27) = 0
  194.         k$ = INKEY$
  195.         'draw everything then process bullets
  196.         drawStars 1
  197.         FOR ai = 1 TO alienN
  198.             drawAliens ai
  199.         NEXT
  200.         FOR i = 1 TO nRocks
  201.             IF r(i).live THEN 'make sure if we crash into a ship it is a live rock, not one sitting on side waiting to be called up
  202.                 drawRock i ' while drawing rocks the ship could be blown up
  203.                 IF ((r(i).x - ship.x) ^ 2 + (r(i).y - ship.y) ^ 2) ^ .5 < r(i).r + 30 THEN 'rock collides with ship?
  204.                     FOR br = 1 TO 200 STEP 5
  205.                         CIRCLE ((ship.x + r(i).x) / 2, (ship.y + r(i).y) / 2), br, _RGB32(255 - br, 255 - 2 * br, 0)
  206.                     NEXT
  207.                     drawRock i
  208.                     drawship
  209.                     ship.live = 0
  210.                     IF i <= rocks THEN newRock i ELSE r(i).live = 0
  211.                 END IF
  212.             END IF
  213.         NEXT
  214.         FOR i = 1 TO nRocks 'smoke up the place with rock debris fields still flying out from hit frames ago
  215.             IF r(i).explodeFrame THEN
  216.                 r(i).explodeFrame = r(i).explodeFrame + 1
  217.                 IF r(i).explodeFrame > .25 * r(i).r THEN
  218.                     r(i).explodeFrame = 0
  219.                     IF i <= rocks THEN newRock i ' now replace the rock
  220.                 ELSE
  221.                     explode r(i).x, r(i).y, r(i).r, r(i).explodeFrame
  222.                 END IF
  223.             END IF
  224.         NEXT
  225.         IF ship.live THEN
  226.             FOR ai = 1 TO alienN
  227.                 IF SQR((aliens(ai).x - ship.x) ^ 2 + (aliens(ai).y - ship.y) ^ 2) < 60 THEN 'aliens and ship collisde boom boom
  228.                     FOR br = 1 TO 200 STEP 5
  229.                         CIRCLE ((ship.x + aliens(ai).x) / 2, (ship.y + aliens(ai).y) / 2), br, _RGB32(255 - br, 255 - 2 * br, 0)
  230.                     NEXT
  231.                     drawship
  232.                     ship.live = 0
  233.                     _CONTINUE
  234.                 ELSE
  235.                     drawship
  236.                 END IF
  237.             NEXT
  238.  
  239.             '                                                                   ship controls update
  240.             'a left spin
  241.             IF _KEYDOWN(97) THEN ship.angle = ship.angle - pi / 48
  242.  
  243.             's right spin
  244.             IF _KEYDOWN(115) THEN ship.angle = ship.angle + pi / 48
  245.  
  246.             'l is Fire!
  247.             fire = 0
  248.             IF _KEYDOWN(108) THEN
  249.                 t = TIMER(.01)
  250.                 IF lastt = 0 OR t - lastt > .1 THEN fire = 1: SOUND 2088, .03: lastt = t
  251.             END IF
  252.             kh = _KEYHIT
  253.             SELECT CASE kh
  254.                 CASE 107 'thrust  k key
  255.                     SOUND 488, 2
  256.                     ship.thrustAngle = ship.angle: ship.thrust = 120
  257.                 CASE 32 ' space = hyperspace jump
  258.                     RANDOMIZE TIMER
  259.                     ship.x = (xmax - 300) * RND + 150: ship.y = (ymax - 300) * RND + 150: ship.thrust = 0
  260.             END SELECT
  261.  
  262.             '                                                                   locate ship
  263.             IF ship.thrust > 0 THEN
  264.                 'relocate ship position
  265.                 ship.x = ship.x + ship.speed * COS(ship.thrustAngle)
  266.                 ship.y = ship.y + ship.speed * SIN(ship.thrustAngle)
  267.             END IF
  268.             '                                                                    jump borders
  269.             IF ship.x < 0 THEN ship.x = xmax - ABS(ship.x)
  270.             IF ship.x > xmax THEN ship.x = ship.x - xmax
  271.             IF ship.y < 0 THEN ship.y = ymax - ABS(ship.y)
  272.             IF ship.y > ymax THEN ship.y = ship.y - ymax
  273.  
  274.  
  275.             FOR i = 0 TO nBullets '                                               handle bullets
  276.                 IF b(i).live = 0 AND fire = 1 THEN 'have inactive bullet to use
  277.                     b(i).x = ship.x + bSpeed * COS(ship.angle)
  278.                     b(i).y = ship.y + bSpeed * SIN(ship.angle)
  279.                     b(i).dx = bSpeed * COS(ship.angle)
  280.                     b(i).dy = bSpeed * SIN(ship.angle)
  281.                     b(i).live = -1
  282.                     bullets = bullets + 1
  283.                     fire = 0
  284.                 END IF
  285.                 IF b(i).live THEN 'new location
  286.                     b(i).x = b(i).x + b(i).dx
  287.                     b(i).y = b(i).y + b(i).dy
  288.                     IF b(i).x > 0 AND b(i).x < xmax AND b(i).y > 0 AND b(i).y < ymax THEN 'in bounds draw it
  289.  
  290.                         'bullet hit aliens?
  291.                         FOR ai = 1 TO alienN
  292.                             IF SQR((aliens(ai).x - b(i).x) ^ 2 + (aliens(ai).y - b(i).y) ^ 2) < 30 THEN
  293.                                 FOR br = 1 TO 120
  294.                                     CIRCLE (aliens(ai).x, aliens(ai).y), br / 3, plasma~&(0)
  295.                                 NEXT
  296.                                 _DISPLAY
  297.                                 _DELAY .05
  298.                                 hits = hits + 1
  299.                                 points = points + 100
  300.                                 aliens(ai).live = 0
  301.                                 newAlien ai
  302.                                 b(i).live = 0
  303.                                 _CONTINUE
  304.                             END IF
  305.                         NEXT
  306.                         FOR r = 1 TO nRocks 'check for collision with rock
  307.                             IF r(r).live THEN
  308.                                 IF SQR((r(r).x - b(i).x) ^ 2 + (r(r).y - b(i).y) ^ 2) < r(r).r THEN 'its a hit!
  309.                                     r(r).explodeFrame = 1 'linger with explosion
  310.                                     r(r).live = 0
  311.                                     hits = hits + 1
  312.                                     points = points + ((r(r).speed - .5) * 50 + (90 - (r(r).r - 10)) * 1.1111) / 2
  313.                                     IF r(r).r > 30 THEN '       split rock  into ? new ones
  314.                                         maxBabyRocks = INT((r(r).r - 10) / 10)
  315.                                         maxBabyRocks = irnd&(2, maxBabyRocks) ' pick a number of baby Rocks
  316.                                         FOR br = 1 TO maxBabyRocks
  317.                                             '                        new rock
  318.                                             newRockN = freeRock& '                          get inactive rock number
  319.                                             newRock newRockN '                              new identity and activate
  320.                                             r(newRockN).r = (r(r).r - 10) / maxBabyRocks '  split in equal parts minus 20% mass
  321.                                             r(newRockN).x = r(r).x + irnd&(-30, 30) '       thrown from parent
  322.                                             r(newRockN).y = r(r).y + irnd&(-30, 30)
  323.                                             r(newRockN).c = r(r).c '                   same color as parent
  324.                                             r(newRockN).heading = rrnd(ship.angle - .75 * pi, ship.angle + .75 * pi)
  325.                                         NEXT
  326.                                     END IF ' big enough to split
  327.                                     b(i).live = 0 'kill bullet
  328.                                 END IF ' hit rock
  329.                             END IF 'rock is there
  330.                         NEXT ' rock
  331.                         IF b(i).live THEN fcirc b(i).x, b(i).y, 3, _RGB32(255, 255, 0) 'draws bullet
  332.                     ELSE
  333.                         b(i).live = 0 'out of bounds
  334.                     END IF ' bullet is in bounds
  335.                 END IF ' bullet live
  336.             NEXT ' bullet
  337.         END IF ' if ship still live
  338.         _DISPLAY
  339.         IF ship.live = 0 THEN
  340.             lives = lives - 1
  341.             IF lives MOD 4 = 0 THEN rocks = rocks + 1
  342.             IF lives MOD 4 = 2 THEN alienN = alienN + 1
  343.             s$ = "Lives:" + STR$(lives) + "  Hits:" + STR$(hits) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits * 100 / bullets)) + "%"
  344.             _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 80), s$
  345.             _FONT fnt2
  346.             s$ = STR$(points) + hs$
  347.             _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  348.             _FONT fnt
  349.             s$ = "Press Enter to enter your next life"
  350.             _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 + 120), s$
  351.             _DISPLAY
  352.             WHILE _KEYDOWN(13) = 0: WEND 'wait for enter key
  353.         ELSE
  354.             _LIMIT 60 ' if ship dies let's rest and regroup  before restart next life
  355.         END IF
  356.     WEND
  357.     _DISPLAY
  358. IF points > HS THEN
  359.     OPEN "Asteroids High Score.txt" FOR OUTPUT AS #1
  360.     PRINT #1, points
  361.     CLOSE #1
  362. ship.x = -200: ship.y = -200 'get it out of the way
  363. i = 0
  364.     drawStars 0
  365.     i = i + 1
  366.     IF i MOD 30 = 29 AND rocks < nRocks THEN rocks = rocks + 1: r(rocks).live = 1
  367.     FOR r = 1 TO nRocks
  368.         IF r(r).live THEN drawRock r
  369.     NEXT
  370.     s$ = "Lives:" + STR$(lives) + "  Hits:" + STR$(hits) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits * 100 / bullets)) + "%"
  371.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 80), s$
  372.     _FONT fnt2
  373.     s$ = STR$(points)
  374.     IF points > HS THEN s$ = s$ + " a New Record!" ELSE s$ = STR$(points) + hs$
  375.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  376.     _FONT fnt
  377.     s$ = "Press q to quit, p or a to Play Again..."
  378.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 + 120), s$
  379.     IF _KEYDOWN(ASC("a")) OR _KEYDOWN(ASC("p")) THEN GOTO restart
  380.     _DISPLAY
  381.     _LIMIT 60
  382.  
  383. SUB drawStars (moving)
  384.     TYPE starType
  385.         x AS SINGLE
  386.         y AS SINGLE
  387.         size AS SINGLE
  388.         c AS INTEGER
  389.     END TYPE
  390.     STATIC beenHere, stars(600) AS starType, cy AS LONG
  391.     DIM i AS LONG
  392.     IF beenHere = 0 THEN 'static part
  393.         FOR i = 0 TO 200
  394.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = 0
  395.             stars(i).c = irnd&(80, 140)
  396.         NEXT
  397.         FOR i = 0 TO 200
  398.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = .3
  399.             stars(i).c = irnd&(80, 140)
  400.         NEXT
  401.  
  402.         FOR i = 1 TO 140
  403.             stars(i + 400).x = RND * xmax: stars(i + 400).y = RND * ymax: stars(i + 100).size = .6
  404.             stars(i).c = irnd&(110, 170)
  405.         NEXT
  406.         FOR i = 1 TO 50
  407.             stars(i + 540).x = RND * xmax: stars(i + 540).y = RND * ymax: stars(i + 170).size = 1.2
  408.             stars(i).c = irnd&(140, 200)
  409.         NEXT
  410.         FOR i = 1 TO 10
  411.             stars(i + 590).x = RND * xmax: stars(i + 590).y = RND * ymax: stars(i + 195).size = 2.4
  412.             stars(i).c = irnd&(170, 235)
  413.         NEXT
  414.         cy = ymax / 2
  415.         beenHere = 1
  416.     END IF
  417.     FOR i = 0 TO cy
  418.         LINE (0, i)-(xmax, i), _RGB32(0, 0, .1 * i + 4)
  419.         LINE (0, ymax - i)-(xmax, ymax - i), _RGB(0, 0, .1 * i + 4)
  420.     NEXT
  421.     FOR i = 0 TO 200
  422.         IF moving THEN
  423.             stars(i).x = stars(i).x + .2 * stars(i).size ^ stars(i).size
  424.             IF stars(i).x > xmax THEN stars(i).x = -1 * RND * 20
  425.         END IF
  426.         fcirc stars(i).x, stars(i).y, stars(i).size, _RGB32(stars(i).c - 10, stars(i).c, stars(i).c + 10)
  427.     NEXT
  428.  
  429. SUB newAlien (i AS LONG)
  430.     DIM side AS LONG, heading
  431.     RANDOMIZE TIMER * RND 'to avoid making twins
  432.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  433.     aliens(i).fireX = irnd(10, xmax - 10)
  434.     aliens(i).fireY = irnd(10, ymax - 10)
  435.     aliens(i).attackFrame = irnd(30, 400) ' EDIT a tweak to survive a little long before getting murdered with low lives over and over...
  436.     SELECT CASE side
  437.         CASE 1
  438.             aliens(i).x = -10
  439.             aliens(i).y = rrnd(20, ymax - 20)
  440.         CASE 2
  441.             aliens(i).x = xmax + 10
  442.             aliens(i).y = rrnd(20, ymax - 20)
  443.         CASE 3
  444.             aliens(i).x = rrnd(20, xmax - 20)
  445.             aliens(i).y = -10
  446.         CASE 4
  447.             aliens(i).x = rrnd(20, xmax - 20)
  448.             aliens(i).y = ymax + 10
  449.     END SELECT
  450.     heading = _ATAN2(aliens(i).fireY - aliens(i).y, aliens(i).fireX - aliens(i).x)
  451.     aliens(i).dx = .5 * COS(heading)
  452.     aliens(i).dy = .5 * SIN(heading)
  453.     aliens(i).live = 0
  454.     aliens(i).transform = 0
  455.     aliens(i).c = _RGB32(irnd(128, 255), irnd(0, 255), irnd(0, 255))
  456.  
  457. FUNCTION plasma~& (new AS LONG)
  458.     STATIC r, g, b, cnt, beenHere
  459.     IF beenHere = 0 OR new THEN
  460.         r = RND: g = RND: b = RND: beenHere = 1: cnt = 0
  461.     END IF
  462.     cnt = cnt + .2
  463.     plasma~& = _RGB32(127 + 127 * SIN(r * cnt), 127 + 127 * SIN(g * cnt), 127 + 127 * SIN(b * cnt))
  464.  
  465. SUB drawAliens (i AS LONG) 'shipType
  466.     DIM light AS LONG, heading, r AS LONG, g AS LONG, b AS LONG
  467.     IF aliens(i).live THEN
  468.         SOUND 6000 + i * 200, .03
  469.         IF aliens(i).transform = 0 THEN
  470.             r = _RED32(aliens(i).c): g = _GREEN32(aliens(i).c): b = _BLUE32(aliens(i).c)
  471.             fellipse aliens(i).x, aliens(i).y, 6, 15, _RGB32(r, g - 120, b - 100)
  472.             fellipse aliens(i).x, aliens(i).y, 18, 11, _RGB32(r, g - 60, b - 50)
  473.             fellipse aliens(i).x, aliens(i).y, 30, 7, _RGB32(r, g, b)
  474.             FOR light = 0 TO 5
  475.                 fcirc aliens(i).x - 30 + 11 * light + aliens(i).ls, aliens(i).y, 1, _RGB32(aliens(i).ls * 50, aliens(i).ls * 50, aliens(i).ls * 50)
  476.             NEXT
  477.             aliens(i).ls = aliens(i).ls + 1
  478.             IF aliens(i).ls > 5 THEN aliens(i).ls = 0
  479.         ELSE
  480.             drawBall aliens(i).x, aliens(i).y, 30, aliens(i).c
  481.         END IF
  482.         'time to shoot?
  483.         aliens(i).x = aliens(i).x + aliens(i).dx
  484.         aliens(i).y = aliens(i).y + aliens(i).dy
  485.         IF SQR((aliens(i).fireX - aliens(i).x) ^ 2 + (aliens(i).fireY - aliens(i).y) ^ 2) < 5 THEN 'transform into the bolder of death
  486.             aliens(i).transform = 1
  487.             heading = _ATAN2(ship.y - aliens(i).y, ship.x - aliens(i).x)
  488.             aliens(i).dx = 2.5 * COS(heading)
  489.             aliens(i).dy = 2.5 * SIN(heading)
  490.         END IF
  491.         IF aliens(i).x < -10 OR aliens(i).x > xmax + 10 THEN
  492.             IF aliens(i).y < -10 OR aliens(i).y > ymax + 10 THEN '  out of bounds goodbye bolder of death!
  493.                 aliens(i).live = 0 'man we dodged a bullet here!!!!
  494.                 newAlien i 'reset the trap
  495.             END IF
  496.         END IF
  497.     ELSE
  498.         IF aliens(i).attackFrame THEN
  499.             aliens(i).attackFrame = aliens(i).attackFrame - 1
  500.             IF aliens(i).attackFrame = 0 THEN
  501.                 aliens(i).live = 1
  502.             END IF
  503.         END IF
  504.     END IF
  505.  
  506. FUNCTION freeRock&
  507.     DIM i AS LONG
  508.     FOR i = rocks + 1 TO nRocks ' look for inactive rock number
  509.         IF r(i).live = 0 AND r(i).explodeFrame = 0 THEN freeRock& = i: EXIT FUNCTION
  510.     NEXT
  511.  
  512. SUB explode (x AS LONG, y AS LONG, r AS LONG, frm AS LONG)
  513.     DIM maxParticles AS LONG, i AS LONG, rounds AS LONG, loopCount AS LONG
  514.     maxParticles = r * 4
  515.     FOR i = 1 TO r
  516.         NewDot i, x, y, r
  517.     NEXT
  518.     rounds = r
  519.     FOR loopCount = 0 TO frm
  520.         IF _KEYDOWN(27) THEN END
  521.         FOR i = 1 TO rounds
  522.             dots(i).x = dots(i).x + dots(i).dx
  523.             dots(i).y = dots(i).y + dots(i).dy
  524.             fcirc dots(i).x, dots(i).y, dots(i).size, dots(i).kolor
  525.         NEXT
  526.         IF rounds < maxParticles THEN
  527.             FOR i = 1 TO r
  528.                 NewDot (rounds + i), x, y, r
  529.             NEXT
  530.             rounds = rounds + r
  531.         END IF
  532.     NEXT
  533.  
  534. SUB NewDot (i AS LONG, x AS LONG, y AS LONG, r AS LONG)
  535.     DIM angle, rd
  536.     angle = pi * 2 * RND
  537.     rd = RND * 30
  538.     dots(i).x = x + rd * COS(angle)
  539.     dots(i).y = y + rd * SIN(angle)
  540.     dots(i).size = RND * r * .05
  541.     rd = RND 'STxAxTIC recommended for rounder spreads
  542.     dots(i).dx = rd * 10 * (10 - 2 * dots(i).size) * COS(angle)
  543.     dots(i).dy = rd * 10 * (10 - 2 * dots(i).size) * SIN(angle)
  544.     rd = 20 + RND * 70
  545.     dots(i).kolor = _RGBA32(rd, rd, rd, 80)
  546.  
  547. SUB drawship 'simple red iso triangle pointed towards radianAngle
  548.     DIM x1 AS LONG, y1 AS LONG, x2 AS LONG, y2 AS LONG, x3 AS LONG, y3 AS LONG
  549.     DIM x4 AS LONG, y4 AS LONG, x5 AS LONG, y5 AS LONG
  550.     IF ship.thrust > 0 THEN
  551.         'burn out flame as thruster dies out
  552.         x4 = ship.x + .5 * ship.thrust * COS(ship.angle - 17 / 18 * pi)
  553.         y4 = ship.y + .5 * ship.thrust * SIN(ship.angle - 17 / 18 * pi)
  554.         x5 = ship.x + .5 * ship.thrust * COS(ship.angle - 19 / 18 * pi)
  555.         y5 = ship.y + .5 * ship.thrust * SIN(ship.angle - 19 / 18 * pi)
  556.         ftri ship.x, ship.y, x4, y4, x5, y5, &H99FFFF88
  557.         ship.thrust = ship.thrust - 1
  558.     END IF
  559.     'draw ship dead or alive thrust or not, calculate 3 points of triangle ship
  560.     fcirc ship.x, ship.y, 30, &H05FFFFFF
  561.     x1 = ship.x + 30 * COS(ship.angle) ' front point
  562.     y1 = ship.y + 30 * SIN(ship.angle) '
  563.     x2 = ship.x + 30 * COS(ship.angle + .6666 * pi) ' wing
  564.     y2 = ship.y + 30 * SIN(ship.angle + .6666 * pi)
  565.     x3 = ship.x + 30 * COS(ship.angle - .6666 * pi) ' other wing
  566.     y3 = ship.y + 30 * SIN(ship.angle - .6666 * pi)
  567.     ftri ship.x, ship.y, x1, y1, x2, y2, _RGB32(80, 120, 80, 80)
  568.     ftri ship.x, ship.y, x1, y1, x3, y3, _RGB32(60, 100, 60, 80)
  569.     LINE (x1, y1)-(ship.x, ship.y), _RGB32(255, 255, 128)
  570.     LINE (x1, y1)-(x2, y2), _RGB32(255, 180, 40)
  571.     LINE (x1, y1)-(x3, y3), _RGB32(255, 180, 40)
  572.  
  573. SUB drawRock (iRock)
  574.     RANDOMIZE USING r(iRock).seed 'this prevents having to save a particular sequence of random number
  575.     DIM dx, dy, j AS LONG, rRad AS SINGLE, leg AS SINGLE, x0 AS LONG, y0 AS LONG, rc AS LONG, c~&, x1 AS LONG, y1 AS LONG, xoff, yoff, i AS LONG
  576.     DIM x2 AS LONG, y2 AS LONG
  577.     dx = r(iRock).speed * COS(r(iRock).heading)
  578.     dy = r(iRock).speed * SIN(r(iRock).heading) 'update location
  579.     r(iRock).ra = r(iRock).ra + r(iRock).spin
  580.     IF r(iRock).x + dx + r(iRock).r < 0 OR r(iRock).x + dx - r(iRock).r > xmax OR r(iRock).y + dy + r(iRock).r < 0 OR r(iRock).y + dy - r(iRock).r > ymax THEN
  581.         IF iRock <= rocks THEN newRock iRock ELSE r(iRock).live = 0
  582.         EXIT SUB ' reassigned get out of here
  583.     ELSE
  584.         r(iRock).x = r(iRock).x + dx
  585.         r(iRock).y = r(iRock).y + dy
  586.     END IF
  587.     FOR j = 10 TO 3 STEP -1 '                  rock drawing (see demo program where developed code)
  588.         rRad = .1 * j * r(iRock).r
  589.         leg = rRad * (RND * .7 + .3)
  590.         x0 = r(iRock).x + leg * COS(r(iRock).ra)
  591.         y0 = r(iRock).y + leg * SIN(r(iRock).ra)
  592.         rc = r(iRock).c + 30 * RND - 15
  593.         c~& = _RGB32(rc + 5, rc - 10, rc + 5)
  594.         x1 = x0
  595.         y1 = y0
  596.         xoff = RND * 20 - 10 + r(iRock).x
  597.         yoff = RND * 20 - 10 + r(iRock).y
  598.         FOR i = 1 TO 12
  599.             leg = rRad * (RND * .35 + .65)
  600.             IF i = 12 THEN
  601.                 x2 = x0: y2 = y0
  602.             ELSE
  603.                 x2 = xoff + leg * COS(i * polyAngle + r(iRock).ra)
  604.                 y2 = yoff + leg * SIN(i * polyAngle + r(iRock).ra)
  605.             END IF
  606.             ftri r(iRock).x, r(iRock).y, x1, y1, x2, y2, c~&
  607.             x1 = x2: y1 = y2
  608.         NEXT
  609.     NEXT
  610.  
  611. SUB newRock (iRock)
  612.     DIM side AS LONG
  613.     RANDOMIZE TIMER * RND 'to avoid making twins
  614.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  615.     SELECT CASE side
  616.         CASE 1
  617.             r(iRock).x = -100
  618.             r(iRock).y = rrnd(20, ymax - 20)
  619.             r(iRock).heading = 3 * pi / 2 + RND * pi
  620.         CASE 2
  621.             r(iRock).x = xmax + 100
  622.             r(iRock).y = rrnd(20, ymax - 20)
  623.             r(iRock).heading = pi / 2 + RND * pi
  624.         CASE 3
  625.             r(iRock).x = rrnd(20, xmax - 20)
  626.             r(iRock).y = -100
  627.             r(iRock).heading = RND * pi
  628.         CASE 4
  629.             r(iRock).x = rrnd(20, xmax - 20)
  630.             r(iRock).y = ymax + 100
  631.             r(iRock).heading = pi + RND * pi
  632.     END SELECT
  633.     r(iRock).speed = rrnd(.5, 2.5) 'speed, rotation angle, radius, gray coloring, spin, seed, hit for explosion
  634.     r(iRock).ra = RND * 2 * pi
  635.     r(iRock).r = irnd&(30, 100)
  636.     r(iRock).c = irnd&(60, 110) ' Ken request increase in rock color
  637.     r(iRock).spin = rrnd(-pi / 20, pi / 20)
  638.     r(iRock).seed = INT(RND * 64000) - 32000
  639.     r(iRock).explodeFrame = 0
  640.     r(iRock).live = 1
  641.  
  642. FUNCTION irnd& (n1, n2) 'return an integer between 2 numbers
  643.     DIM l%, h%
  644.     IF n1 > n2 THEN l% = n2: h% = n1 ELSE l% = n1: h% = n2
  645.     irnd& = INT(RND * (h% - l% + 1)) + l%
  646.  
  647. FUNCTION rrnd (n1, n2) ' return number (expecting reals =_single, double, _float depending on default / define setup)
  648.     rrnd = (n2 - n1) * RND + n1
  649.  
  650. SUB drawBall (x, y, r, c AS _UNSIGNED LONG)
  651.     DIM red AS LONG, grn AS LONG, blu AS LONG, rr AS LONG, f
  652.     red = _RED32(c): grn = _GREEN32(c): blu = _BLUE32(c)
  653.     FOR rr = r TO 0 STEP -1
  654.         f = 1 - rr / r
  655.         fcirc x, y, rr, _RGB32(red * f, grn * f, blu * f)
  656.     NEXT
  657.  
  658. SUB fellipse (CX AS LONG, CY AS LONG, xr AS LONG, yr AS LONG, C AS _UNSIGNED LONG)
  659.     IF xr = 0 OR yr = 0 THEN EXIT SUB
  660.     DIM x AS LONG, y AS LONG
  661.     w2 = xr * xr: h2 = yr * yr: h2w2 = h2 * w2
  662.     LINE (CX - xr, CY)-(CX + xr, CY), C, BF
  663.     DO WHILE y < yr
  664.         y = y + 1
  665.         x = SQR((h2w2 - y * y * w2) \ h2)
  666.         LINE (CX - x, CY + y)-(CX + x, CY + y), C, BF
  667.         LINE (CX - x, CY - y)-(CX + x, CY - y), C, BF
  668.     LOOP
  669.  
  670. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  671.     DIM D AS LONG
  672.     STATIC a&
  673.     D = _DEST
  674.     IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32)
  675.     _DEST a&
  676.     _DONTBLEND a& '  '<<<< new 2019-12-16 fix
  677.     PSET (0, 0), K
  678.     _BLEND a& '<<<< new 2019-12-16 fix
  679.     _DEST D
  680.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  681.  
  682. SUB fcirc (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG) 'vince version
  683.     DIM x0 AS LONG, y0 AS LONG, e AS LONG
  684.     x0 = R: y0 = 0: e = 0
  685.     DO WHILE y0 < x0
  686.         IF e <= 0 THEN
  687.             y0 = y0 + 1
  688.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  689.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  690.             e = e + 2 * y0
  691.         ELSE
  692.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  693.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  694.             x0 = x0 - 1: e = e - 2 * x0
  695.         END IF
  696.     LOOP
  697.     LINE (x - R, y)-(x + R, y), C, BF
  698.  

If you have Windows, I don't think you even need the Font file in the zip in the Original Post.

Hey 2nd time out with M9 and this!
 
Holy Cow howd that happen!.PNG
« Last Edit: November 04, 2020, 11:12:30 pm by bplus »

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: b+ Asteroids makeover
« Reply #70 on: November 04, 2020, 11:59:51 pm »
Awesome job! I like the new sounds. I didn't know the SOUND command could have such a high frequency and low time on them. I have one suggestion though if you want to keep working on this. Use the player's score to either speed things up or add asteroids and saucers to them. For example, every 5,000 the speed could increase by a certain amount or another asteroid or saucer is added on the screen. But that's all I will say because this is really good!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #71 on: November 05, 2020, 10:02:46 am »
My last post from late last night is missing. Come to think the forum became inaccessible just after but the post was made?

Anyway I had new high score over 84,000.

Quote
I have one suggestion though if you want to keep working on this. Use the player's score to either speed things up or add asteroids and saucers to them.

Every other new life does get harder adding one more parent rock or alien to the game. I think I did slow down the speeds and lowered number of rocks from the mouse shooter versions so people can get use to the A&S turns and K&L thrust and fire buttons.

Number of rocks are started after first main loop handling lives, rocks are reset just before entering the main life loop you can increase them back to 5 or 6 to start and they will increase from there with lives left.

Under newRock and newAlien speeds are set by random number between an upper and lower bound, points for hitting rocks are based on speed and size so try to keep... oh I better set the range as variables that you can adjust or can be adjusted in game code because points are based on max/min speeds.


Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: b+ Asteroids makeover
« Reply #72 on: November 05, 2020, 10:24:26 am »
Good work!  Fun.  I did change the keys to fit my laptop keyboard layout more comfortably (L/R arrows for control, UP for thrust, space for fire, enter for hyperspace).  After that, it's an enjoyable play here.  I'm going to see how high a score I can get now.  My wife is gone this morning, so I can play away!

EDIT:  How about adding a current score & high score display during game play?  I stuck in a LOCATE 1, 32: PRINT points; " / "; HS; before the _DISPLAY call at the bottom of the IF ship.live area, and before the _DISPLAY call after the ufo explodes.  It doesn't seem to slow anything down here, and adds a visual goal to reach.  I also put in a pause game key here for taking a break.

Game is getting fun to waste time with, and it doesn't cost me .25 cents to play. Thanks.

- Dav 
« Last Edit: November 05, 2020, 11:09:13 am by Dav »

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: b+ Asteroids makeover
« Reply #73 on: November 05, 2020, 11:58:46 am »
Thanks B+, I might tinker around with it later today. Really cool game! Hopefully the final version of this game goes into the Games section of the forum.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #74 on: November 05, 2020, 04:33:16 pm »
M10 mods based on latest comments, have it both ways: arrows or AS and K. Fire is continuous why beat the keyboard up? A little score board in top left corner, I've been wondering about rocks being hit PUS score for round PLUS lives update. Constants added for tinkering with speeds and sizes.

Code: QB64: [Select]
  1. _TITLE "b+QB64 Asteroids M10" 'started 2018-07-13
  2. '2020 - Oct and Nov: Special thanks to SierraKen who has been helpful with suggestions, ideas and fixes.
  3.  
  4. ' Far far away in a universe where Newton's 1st Law of Motion is not obeyed...    ;-))
  5.  
  6.  
  7. '                                            New Controls
  8. ' key a or left arrow = turn left
  9. ' key s or right arrow = turn right
  10. ' enter or spacebar =  "hyperspace" show up somewhere else  better or worse use when collision is imminent
  11. ' key k or up arrow = thrust  just a burst in direction you are pointed but doesn't last
  12. ' fire! owwha, owha, owha...  is now continuous
  13.  
  14. '=================================================================================================================
  15.  
  16. ' 2020-10-27 remove the alternate subs and get down below 200 LOC almost there now! new shooter action font and background
  17. ' 2020-10-28 another makeover explosions and split asteroids
  18. ' 2020-10-29 fix baby rock management, break between lives
  19. ' 2020-10-29 fix left/right gun, fix explosions over many frames to eliminate pause in action, speed up 60 fps
  20. ' 2020-10-30 m3 SierraKen's idea to angle shooter with mousewheel also finish WASD options, more rocks, points system
  21. ' points:
  22. ' The higher the speed the better    speed range .5 to 2.5, diff = 2 * 50 = 100          s - .5 * 50
  23. ' DELETE The lower the color the better   color range 10 to 60, diff =      50 * 2 = 100  50 - (c - 10) * 2
  24. ' The smaller the size the better  size range 10 to 100, diff = 90 * 1.1111 = 100  90 - (sz -10) * 1.1111
  25. '        ((speed - .5) * 50 + (90 - (r - 10)) * 1.1111) / 2 = 100 best score per hit
  26. ' 2020-10-30 increase level of difficulty, fix double lives lost, add an ending after all lives spent.
  27. ' 2020-10-31 M4 They are Here - the aliens have accepted my invitaion for war games don't get caught in their beam.
  28. ' rework ending and variable LONG suffix. Aliens on the attack 100 points before or after transformed into the Bolder of Death.
  29. ' 2020-11-01 M5 FX Moving through space, Oh yeah, more aliens!
  30. ' 2020-11-01 M6 add play again and save high game , continuous shoot
  31. ' 2020-11-01 M7 fix hits count when hit alien ship or Bolder of Death. Fix lights on aliens ship. I want to see collsions with ship.
  32. ' Ken recommends removing text in middle of screen, yeah, distracting. Makeover ship as with mouse x, y it's center. Add Splash screen.
  33. ' Show mouse in between lives so can be in screen center when press key to start next run.
  34.  
  35. ' 2020-11-03 M9 watching videos on Asteroids, I found a view and description of the control panel, it is:
  36. ' 2 buttons on left and lower button in middle and 2 buttons on right level with 2 on left.
  37. ' 2 buttons on left are left and right turns they will be Keys A and S
  38. ' The middle will be spacebar for Hypespace or these days we might call it worm hole, jump to another location better or worse!
  39. ' 2 buttons on right K and L: K will be a thruster of sorts you eventually come to a stop (not what Newton would like) L is the fire button.
  40. ' So let's try that. I am impressed by hitting thruster and shooting all around as you dift in direction gun was pointed when hit thruster.
  41. ' Lighten rocks and change points, based now only on size and speed of Asteroids.
  42. ' 2020-11-04 M9 Install new update to thrust control. Thanks to SierraKen for finding out what happened to Hyperspace jump when press
  43. ' spacebar a 2nd time in a life. Oh also Boulders of Death are now more like smooth colored spheres. Ahhhh Fixed the crashing at the borders
  44. ' now fly out one side and come back in on the other! This is getting good! Adding some sound effects.
  45. ' 2020-11-05 M10 set some constants for starting game so can just change them to level of play desired.
  46. ' speed points =  50 * (rockSpeed - minRockSpeed)/rockSpeedRange > fastest rock gets 50 points
  47. ' size points = 50 * (rockSizeRange - (rockSize - minRockSize))/rockSizeRange  > smallest rock gets 50 points
  48. ' points = points +  50 * ( (rockSpeed - minRockSpeed)/rockSpeedRange +  (rockSizeRange - (rockSize - minRockSize))/rockSizeRange )
  49. ' Dav's comments: Add arrow keys for left right turns and up for thrust, continuous fire now! A little score board in top left corner.
  50. ' Dav I am keeping spacebar for Hyperspace but also Enter, don't need fire button now.
  51. ' Try the A for left and the right arrow for right turns.
  52.  
  53. '================================================================================================================
  54.  
  55. '    NOTE: !!!!!!!!!!!!!!!   When there is a pause in action, just press enter,  as in enter a new life!
  56.  
  57. '================================================================================================================
  58.  
  59. CONST xmax = 1200, ymax = 700, pi = _PI, polyAngle = _PI / 6, nRocks = 300, nBullets = 2000, bSpeed = 15
  60. CONST startRocks = 2, minRockSpeed = 0.5000, maxRockSpeed = 2.5000, minRockSize = 10, maxRockSize = 100
  61. CONST rockSpeedRange = maxRockSpeed - minRockSpeed, rockSizeRange = maxRockSize - minRockSize
  62. CONST alienSpeed = rockSpeedRange / 2 + minRockSpeed ' average rock speed
  63.  
  64. TYPE alienType
  65.     x AS SINGLE
  66.     y AS SINGLE
  67.     dx AS SINGLE
  68.     dy AS SINGLE
  69.     ls AS LONG ' lights offset and gray scale
  70.     c AS _UNSIGNED LONG ' color
  71.     live AS LONG
  72.     attackFrame AS LONG
  73.     fireX AS SINGLE
  74.     fireY AS SINGLE
  75.     transform AS LONG
  76.  
  77. TYPE particle
  78.     x AS SINGLE
  79.     y AS SINGLE
  80.     dx AS SINGLE
  81.     dy AS SINGLE
  82.     size AS SINGLE
  83.     kolor AS _UNSIGNED LONG
  84.  
  85. TYPE bullet
  86.     x AS SINGLE
  87.     y AS SINGLE
  88.     dx AS SINGLE
  89.     dy AS SINGLE
  90.     live AS LONG
  91.  
  92. TYPE shipType
  93.     x AS SINGLE
  94.     y AS SINGLE
  95.     live AS LONG
  96.     speed AS SINGLE '       just a constant now when Thrust is applied
  97.     thrustAngle AS SINGLE ' ship/gun angle at moment Thrust is pressed
  98.     angle AS SINGLE '       rotated position ship/gun now A or S keypress or hold down
  99.     thrust AS LONG '        this now tracks how many frames ship will move at speed and thrustAngle
  100.  
  101. TYPE rock
  102.     x AS SINGLE
  103.     y AS SINGLE
  104.     r AS LONG '            radius
  105.     ra AS SINGLE '         rotation position   a = a + spin
  106.     heading AS SINGLE '    heading from which dx, dy are calc with speed
  107.     speed AS SINGLE '      speed
  108.     spin AS SINGLE '       rotation direction and amount
  109.     seed AS LONG '         for drawing rocks with RND USING
  110.     c AS LONG '            color   rgb(c, c, c)
  111.     live AS LONG '         need this to track rocks still active like bullets
  112.     explodeFrame AS LONG ' after a rock is hit by bullet, it explodes and in more than one frame
  113.  
  114. REDIM SHARED aliens(1 TO 5) AS alienType
  115. DIM SHARED dots(2000) AS particle ' explosions
  116. DIM SHARED b(nBullets) AS bullet
  117. DIM SHARED ship AS shipType
  118. DIM SHARED r(nRocks) AS rock
  119. DIM SHARED points AS LONG
  120. DIM SHARED rocks AS LONG 'rocks is the minimum number of parent rocks to have on screen  automatic replace when hit or out of bounds
  121.  
  122. DIM HS AS LONG, fnt AS LONG, fnt2 AS LONG ' file LOAD handles
  123. DIM i AS LONG, bullets AS LONG, fire AS LONG ' index and bullets
  124. DIM r AS LONG, newRockN AS LONG, maxBabyRocks AS LONG, br AS LONG, hits AS LONG ' rock stuff
  125. DIM ai AS LONG, alienN AS LONG ' alien index and number
  126. DIM kh AS LONG 'key hit for ship thrust k or up arrow or hyperspace jump spacebar
  127. DIM hs$, s$, k$, t, lastt 'high score, general string and times for bullets
  128. DIM rockPoints AS LONG, roundPoints AS LONG ' various points scores
  129. ship.speed = 3.5 'this would be a constant but ship has to declared as Ship Type first, Hyperspace jump
  130.  
  131. SCREEN _NEWIMAGE(xmax, ymax, 32)
  132. _SCREENMOVE 100, 20
  133.  
  134. fnt = _LOADFONT("ARLRDBD.ttf", 16, "MONOSPACE")
  135. fnt2 = _LOADFONT("ARLRDBD.ttf", 40, "MONOSPACE")
  136. _FONT fnt2
  137. COLOR &HFF00FFFF, &H00000000
  138.  
  139. IF _FILEEXISTS("Asteroids High Score.txt") THEN
  140.     OPEN "Asteroids High Score.txt" FOR INPUT AS #1
  141.     INPUT #1, HS
  142.     CLOSE #1
  143. hs$ = "High Score:" + STR$(HS)
  144.  
  145. 'a little splash screen
  146. rocks = 7: alienN = 3
  147. FOR i = 1 TO nRocks
  148.     newRock i
  149.     IF i > rocks THEN r(i).live = 0
  150. FOR i = 1 TO alienN
  151.     newAlien i
  152. i = 0
  153.     drawStars 0
  154.     i = i + 1
  155.     IF i MOD 30 = 29 AND rocks < nRocks THEN rocks = rocks + 1: r(rocks).live = 1
  156.     FOR r = 1 TO nRocks
  157.         IF r(r).live THEN drawRock r
  158.     NEXT
  159.     FOR i = 1 TO alienN
  160.         drawAliens i
  161.     NEXT
  162.     _FONT fnt2
  163.     s$ = "*** b+QB64 Asteroids ***"
  164.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 60), s$
  165.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(hs$)) / 2, 140), hs$
  166.     s$ = "A or arrow = Left spin"
  167.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 220), s$
  168.     s$ = "S or arrow = Right Spin"
  169.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 300), s$
  170.     s$ = "Space or Enter = Hyper jump"
  171.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 380), s$
  172.     s$ = "K or up arrow = Thrust"
  173.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 460), s$
  174.     s$ = "Escape quit, any plays"
  175.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, 540), s$
  176.     _FONT fnt
  177.     k$ = INKEY$
  178.     _DISPLAY
  179.     _LIMIT 60
  180.  
  181. restart:
  182. IF _FILEEXISTS("Asteroids High Score.txt") THEN
  183.     OPEN "Asteroids High Score.txt" FOR INPUT AS #1
  184.     INPUT #1, HS
  185.     CLOSE #1
  186. hs$ = "  High Score:" + STR$(HS)
  187. lives = 10: alienN = 1: rocks = startRocks: ' always active rocks
  188. points = 0: hits = 0: bullets = 0
  189. WHILE lives > 0 AND _KEYDOWN(27) = 0 ' init start restart
  190.     REDIM aliens(1 TO alienN) AS alienType
  191.     FOR ai = 1 TO alienN
  192.         newAlien ai
  193.     NEXT
  194.     FOR i = 1 TO nRocks 'reset rocks mainly clear baby rocks
  195.         newRock (i)
  196.         IF i > rocks THEN r(i).live = 0
  197.     NEXT
  198.     ship.x = xmax / 2 'avoids explosions top left corner at start, dang still get some!
  199.     ship.y = ymax / 2
  200.     ship.angle = 0
  201.     ship.thrustAngle = 0
  202.     ship.thrust = 0
  203.     ship.live = 1
  204.     rockPoints = 0
  205.     roundPoints = 0
  206.     WHILE ship.live AND _KEYDOWN(27) = 0
  207.  
  208.         _KEYCLEAR 'clear all previous INKEY$ or _KEYHIT and variables  so ship should always start in middle of sceen pointed east
  209.         kh = 0
  210.  
  211.         'draw everything then process bullets
  212.         drawStars 1
  213.         LOCATE 1, 1: PRINT "Lives:"; lives
  214.         LOCATE 2, 1: PRINT "Last Rock:"; STR$(rockPoints)
  215.         LOCATE 3, 1: PRINT "Round:;"; STR$(roundPoints)
  216.         LOCATE 4, 1: PRINT "Points:"; STR$(points)
  217.         LOCATE 5, 1: PRINT "High Score:"; STR$(HS)
  218.         FOR ai = 1 TO alienN
  219.             drawAliens ai
  220.         NEXT
  221.         FOR i = 1 TO nRocks
  222.             IF r(i).live THEN 'make sure if we crash into a ship it is a live rock, not one sitting on side waiting to be called up
  223.                 drawRock i ' while drawing rocks the ship could be blown up
  224.                 IF ((r(i).x - ship.x) ^ 2 + (r(i).y - ship.y) ^ 2) ^ .5 < r(i).r + 30 THEN 'rock collides with ship?
  225.                     FOR br = 1 TO 200 STEP 5
  226.                         CIRCLE ((ship.x + r(i).x) / 2, (ship.y + r(i).y) / 2), br, _RGB32(255 - br, 255 - 2 * br, 0)
  227.                     NEXT
  228.                     drawRock i
  229.                     drawship
  230.                     ship.live = 0
  231.                     IF i <= rocks THEN newRock i ELSE r(i).live = 0
  232.                 END IF
  233.             END IF
  234.         NEXT
  235.         FOR i = 1 TO nRocks 'smoke up the place with rock debris fields still flying out from hit frames ago
  236.             IF r(i).explodeFrame THEN
  237.                 r(i).explodeFrame = r(i).explodeFrame + 1
  238.                 IF r(i).explodeFrame > .25 * r(i).r THEN
  239.                     r(i).explodeFrame = 0
  240.                     IF i <= rocks THEN newRock i ' now replace the rock
  241.                 ELSE
  242.                     explode r(i).x, r(i).y, r(i).r, r(i).explodeFrame
  243.                 END IF
  244.             END IF
  245.         NEXT
  246.         IF ship.live THEN
  247.             FOR ai = 1 TO alienN
  248.                 IF SQR((aliens(ai).x - ship.x) ^ 2 + (aliens(ai).y - ship.y) ^ 2) < 60 THEN 'aliens and ship collisde boom boom
  249.                     FOR br = 1 TO 200 STEP 5
  250.                         CIRCLE ((ship.x + aliens(ai).x) / 2, (ship.y + aliens(ai).y) / 2), br, _RGB32(255 - br, 255 - 2 * br, 0)
  251.                     NEXT
  252.                     drawship
  253.                     ship.live = 0
  254.                     _CONTINUE
  255.                 ELSE
  256.                     drawship
  257.                 END IF
  258.             NEXT
  259.  
  260.             '                                                                   ship controls update
  261.             'a key or left arrow = left spin
  262.             IF _KEYDOWN(97) OR _KEYDOWN(19200) THEN ship.angle = ship.angle - pi / 48
  263.  
  264.             's key or right arrow = right spin
  265.             IF _KEYDOWN(115) OR _KEYDOWN(19712) THEN ship.angle = ship.angle + pi / 48
  266.  
  267.             'l is Fire!  JUST CONTINUOUS FIRE
  268.             fire = 0
  269.             'IF _KEYDOWN(108) THEN
  270.             t = TIMER(.01)
  271.             IF lastt = 0 OR t - lastt > .15 THEN fire = 1: SOUND 2088, .01: lastt = t
  272.             'END IF
  273.  
  274.             kh = _KEYHIT
  275.             SELECT CASE kh
  276.                 CASE 107, 18432 'thrust  k key or up arrow
  277.                     SOUND 488, .01
  278.                     ship.thrustAngle = ship.angle: ship.thrust = 120
  279.                 CASE 13, 32 ' space = hyperspace jump
  280.                     RANDOMIZE TIMER
  281.                     ship.x = (xmax - 300) * RND + 150: ship.y = (ymax - 300) * RND + 150: ship.thrust = 0
  282.             END SELECT
  283.  
  284.             '                                                                   locate ship
  285.             IF ship.thrust > 0 THEN
  286.                 'relocate ship position
  287.                 ship.x = ship.x + ship.speed * COS(ship.thrustAngle)
  288.                 ship.y = ship.y + ship.speed * SIN(ship.thrustAngle)
  289.             END IF
  290.             '                                                                    jump borders
  291.             IF ship.x < 0 THEN ship.x = xmax - ABS(ship.x)
  292.             IF ship.x > xmax THEN ship.x = ship.x - xmax
  293.             IF ship.y < 0 THEN ship.y = ymax - ABS(ship.y)
  294.             IF ship.y > ymax THEN ship.y = ship.y - ymax
  295.  
  296.  
  297.             FOR i = 0 TO nBullets '                                               handle bullets
  298.                 IF b(i).live = 0 AND fire = 1 THEN 'have inactive bullet to use
  299.                     b(i).x = ship.x + bSpeed * COS(ship.angle)
  300.                     b(i).y = ship.y + bSpeed * SIN(ship.angle)
  301.                     b(i).dx = bSpeed * COS(ship.angle)
  302.                     b(i).dy = bSpeed * SIN(ship.angle)
  303.                     b(i).live = -1
  304.                     bullets = bullets + 1
  305.                     fire = 0
  306.                 END IF
  307.                 IF b(i).live THEN 'new location
  308.                     b(i).x = b(i).x + b(i).dx
  309.                     b(i).y = b(i).y + b(i).dy
  310.                     IF b(i).x > 0 AND b(i).x < xmax AND b(i).y > 0 AND b(i).y < ymax THEN 'in bounds draw it
  311.  
  312.                         'bullet hit aliens?
  313.                         FOR ai = 1 TO alienN
  314.                             IF SQR((aliens(ai).x - b(i).x) ^ 2 + (aliens(ai).y - b(i).y) ^ 2) < 30 THEN
  315.                                 FOR br = 1 TO 120
  316.                                     CIRCLE (aliens(ai).x, aliens(ai).y), br / 3, plasma~&(0)
  317.                                 NEXT
  318.                                 _DISPLAY
  319.                                 _DELAY .05
  320.                                 hits = hits + 1
  321.                                 roundPoints = roundPoints + 100
  322.                                 points = points + 100
  323.                                 aliens(ai).live = 0
  324.                                 newAlien ai
  325.                                 b(i).live = 0
  326.                                 _CONTINUE
  327.                             END IF
  328.                         NEXT
  329.                         FOR r = 1 TO nRocks 'check for collision with rock
  330.                             IF r(r).live THEN
  331.                                 IF SQR((r(r).x - b(i).x) ^ 2 + (r(r).y - b(i).y) ^ 2) < r(r).r THEN 'its a hit!
  332.                                     r(r).explodeFrame = 1 'linger with explosion
  333.                                     r(r).live = 0
  334.                                     hits = hits + 1
  335.                                     rockPoints = 50 * ((r(r).speed - minRockSpeed) / rockSpeedRange + (rockSizeRange - (r(r).r - minRockSize)) / rockSizeRange)
  336.                                     roundPoints = roundPoints + rockPoints
  337.                                     points = points + rockPoints
  338.                                     IF r(r).r > 30 THEN '       split rock  into ? new ones
  339.                                         maxBabyRocks = INT((r(r).r - 10) / 10)
  340.                                         maxBabyRocks = irnd&(2, maxBabyRocks) ' pick a number of baby Rocks
  341.                                         FOR br = 1 TO maxBabyRocks
  342.                                             '                        new rock
  343.                                             newRockN = freeRock& '                          get inactive rock number
  344.                                             newRock newRockN '                              new identity and activate
  345.                                             r(newRockN).r = (r(r).r - 10) / maxBabyRocks '  split in equal parts minus 20% mass
  346.                                             r(newRockN).x = r(r).x + irnd&(-30, 30) '       thrown from parent
  347.                                             r(newRockN).y = r(r).y + irnd&(-30, 30)
  348.                                             r(newRockN).c = r(r).c '                   same color as parent
  349.                                             r(newRockN).heading = rrnd(ship.angle - .75 * pi, ship.angle + .75 * pi)
  350.                                         NEXT
  351.                                     END IF ' big enough to split
  352.                                     b(i).live = 0 'kill bullet
  353.                                 END IF ' hit rock
  354.                             END IF 'rock is there
  355.                         NEXT ' rock
  356.                         IF b(i).live THEN fcirc b(i).x, b(i).y, 3, _RGB32(255, 255, 0) 'draws bullet
  357.                     ELSE
  358.                         b(i).live = 0 'out of bounds
  359.                     END IF ' bullet is in bounds
  360.                 END IF ' bullet live
  361.             NEXT ' bullet
  362.         END IF ' if ship still live
  363.         _DISPLAY
  364.         IF ship.live = 0 THEN
  365.             lives = lives - 1
  366.             IF lives MOD 4 = 0 THEN rocks = rocks + 1
  367.             IF lives MOD 4 = 2 THEN alienN = alienN + 1
  368.             s$ = "Lives:" + STR$(lives) + "  Hits:" + STR$(hits) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits * 100 / bullets)) + "%"
  369.             _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 80), s$
  370.             _FONT fnt2
  371.             s$ = STR$(points) + hs$
  372.             _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  373.             _FONT fnt
  374.             s$ = "Press enter to enter next life."
  375.             _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 + 120), s$
  376.             _DISPLAY
  377.             kh = 0
  378.             WHILE kh <> 13
  379.                 kh = _KEYHIT
  380.             WEND 'wait for enter key
  381.         ELSE
  382.             _LIMIT 60 ' if ship dies let's rest and regroup  before restart next life
  383.         END IF
  384.     WEND
  385.     _DISPLAY
  386. IF points > HS THEN
  387.     OPEN "Asteroids High Score.txt" FOR OUTPUT AS #1
  388.     PRINT #1, points
  389.     CLOSE #1
  390. ship.x = -200: ship.y = -200 'get it out of the way
  391. i = 0
  392.     drawStars 0
  393.     i = i + 1
  394.     IF i MOD 30 = 29 AND rocks < nRocks THEN rocks = rocks + 1: r(rocks).live = 1
  395.     FOR r = 1 TO nRocks
  396.         IF r(r).live THEN drawRock r
  397.     NEXT
  398.     s$ = "Lives:" + STR$(lives) + "  Hits:" + STR$(hits) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits * 100 / bullets)) + "%"
  399.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 80), s$
  400.     _FONT fnt2
  401.     s$ = STR$(points)
  402.     IF points > HS THEN s$ = s$ + " a New Record!" ELSE s$ = STR$(points) + hs$
  403.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  404.     _FONT fnt
  405.     s$ = "Press q to quit, p or a to Play Again..."
  406.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 + 120), s$
  407.     IF _KEYDOWN(ASC("a")) OR _KEYDOWN(ASC("p")) THEN GOTO restart
  408.     _DISPLAY
  409.     _LIMIT 60
  410.  
  411. SUB drawStars (moving)
  412.     TYPE starType
  413.         x AS SINGLE
  414.         y AS SINGLE
  415.         size AS SINGLE
  416.         c AS INTEGER
  417.     END TYPE
  418.     STATIC beenHere, stars(600) AS starType, cy AS LONG
  419.     DIM i AS LONG
  420.     IF beenHere = 0 THEN 'static part
  421.         FOR i = 0 TO 200
  422.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = 0
  423.             stars(i).c = irnd&(80, 140)
  424.         NEXT
  425.         FOR i = 0 TO 200
  426.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = .3
  427.             stars(i).c = irnd&(80, 140)
  428.         NEXT
  429.  
  430.         FOR i = 1 TO 140
  431.             stars(i + 400).x = RND * xmax: stars(i + 400).y = RND * ymax: stars(i + 100).size = .6
  432.             stars(i).c = irnd&(110, 170)
  433.         NEXT
  434.         FOR i = 1 TO 50
  435.             stars(i + 540).x = RND * xmax: stars(i + 540).y = RND * ymax: stars(i + 170).size = 1.2
  436.             stars(i).c = irnd&(140, 200)
  437.         NEXT
  438.         FOR i = 1 TO 10
  439.             stars(i + 590).x = RND * xmax: stars(i + 590).y = RND * ymax: stars(i + 195).size = 2.4
  440.             stars(i).c = irnd&(170, 235)
  441.         NEXT
  442.         cy = ymax / 2
  443.         beenHere = 1
  444.     END IF
  445.     FOR i = 0 TO cy
  446.         LINE (0, i)-(xmax, i), _RGB32(0, 0, .1 * i + 4)
  447.         LINE (0, ymax - i)-(xmax, ymax - i), _RGB(0, 0, .1 * i + 4)
  448.     NEXT
  449.     FOR i = 0 TO 200
  450.         IF moving THEN
  451.             stars(i).x = stars(i).x + .2 * stars(i).size ^ stars(i).size
  452.             IF stars(i).x > xmax THEN stars(i).x = -1 * RND * 20
  453.         END IF
  454.         fcirc stars(i).x, stars(i).y, stars(i).size, _RGB32(stars(i).c - 10, stars(i).c, stars(i).c + 10)
  455.     NEXT
  456.  
  457. SUB newAlien (i AS LONG)
  458.     DIM side AS LONG, heading
  459.     RANDOMIZE TIMER * RND 'to avoid making twins
  460.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  461.     aliens(i).fireX = irnd(10, xmax - 10)
  462.     aliens(i).fireY = irnd(10, ymax - 10)
  463.     aliens(i).attackFrame = irnd(30, 400) ' EDIT a tweak to survive a little long before getting murdered with low lives over and over...
  464.     SELECT CASE side
  465.         CASE 1
  466.             aliens(i).x = -10
  467.             aliens(i).y = rrnd(20, ymax - 20)
  468.         CASE 2
  469.             aliens(i).x = xmax + 10
  470.             aliens(i).y = rrnd(20, ymax - 20)
  471.         CASE 3
  472.             aliens(i).x = rrnd(20, xmax - 20)
  473.             aliens(i).y = -10
  474.         CASE 4
  475.             aliens(i).x = rrnd(20, xmax - 20)
  476.             aliens(i).y = ymax + 10
  477.     END SELECT
  478.     heading = _ATAN2(aliens(i).fireY - aliens(i).y, aliens(i).fireX - aliens(i).x)
  479.     aliens(i).dx = alienSpeed * COS(heading)
  480.     aliens(i).dy = alienSpeed * SIN(heading)
  481.     aliens(i).live = 0
  482.     aliens(i).transform = 0
  483.     aliens(i).c = _RGB32(irnd(128, 255), irnd(0, 255), irnd(0, 255))
  484.  
  485. FUNCTION plasma~& (new AS LONG)
  486.     STATIC r, g, b, cnt, beenHere
  487.     IF beenHere = 0 OR new THEN
  488.         r = RND: g = RND: b = RND: beenHere = 1: cnt = 0
  489.     END IF
  490.     cnt = cnt + .2
  491.     plasma~& = _RGB32(127 + 127 * SIN(r * cnt), 127 + 127 * SIN(g * cnt), 127 + 127 * SIN(b * cnt))
  492.  
  493. SUB drawAliens (i AS LONG) 'shipType
  494.     DIM light AS LONG, heading, r AS LONG, g AS LONG, b AS LONG
  495.     IF aliens(i).live THEN
  496.         SOUND 6000 + i * 200, .07
  497.         IF aliens(i).transform = 0 THEN
  498.             r = _RED32(aliens(i).c): g = _GREEN32(aliens(i).c): b = _BLUE32(aliens(i).c)
  499.             fellipse aliens(i).x, aliens(i).y, 6, 15, _RGB32(r, g - 120, b - 100)
  500.             fellipse aliens(i).x, aliens(i).y, 18, 11, _RGB32(r, g - 60, b - 50)
  501.             fellipse aliens(i).x, aliens(i).y, 30, 7, _RGB32(r, g, b)
  502.             FOR light = 0 TO 5
  503.                 fcirc aliens(i).x - 30 + 11 * light + aliens(i).ls, aliens(i).y, 1, _RGB32(aliens(i).ls * 50, aliens(i).ls * 50, aliens(i).ls * 50)
  504.             NEXT
  505.             aliens(i).ls = aliens(i).ls + 1
  506.             IF aliens(i).ls > 5 THEN aliens(i).ls = 0
  507.         ELSE
  508.             drawBall aliens(i).x, aliens(i).y, 30, aliens(i).c
  509.         END IF
  510.         'time to shoot?
  511.         aliens(i).x = aliens(i).x + aliens(i).dx
  512.         aliens(i).y = aliens(i).y + aliens(i).dy
  513.         IF SQR((aliens(i).fireX - aliens(i).x) ^ 2 + (aliens(i).fireY - aliens(i).y) ^ 2) < 5 THEN 'transform into the bolder of death
  514.             aliens(i).transform = 1
  515.             heading = _ATAN2(ship.y - aliens(i).y, ship.x - aliens(i).x)
  516.             aliens(i).dx = 2.5 * COS(heading)
  517.             aliens(i).dy = 2.5 * SIN(heading)
  518.         END IF
  519.         IF aliens(i).x < -10 OR aliens(i).x > xmax + 10 THEN
  520.             IF aliens(i).y < -10 OR aliens(i).y > ymax + 10 THEN '  out of bounds goodbye bolder of death!
  521.                 aliens(i).live = 0 'man we dodged a bullet here!!!!
  522.                 newAlien i 'reset the trap
  523.             END IF
  524.         END IF
  525.     ELSE
  526.         IF aliens(i).attackFrame THEN
  527.             aliens(i).attackFrame = aliens(i).attackFrame - 1
  528.             IF aliens(i).attackFrame = 0 THEN
  529.                 aliens(i).live = 1
  530.             END IF
  531.         END IF
  532.     END IF
  533.  
  534. FUNCTION freeRock&
  535.     DIM i AS LONG
  536.     FOR i = rocks + 1 TO nRocks ' look for inactive rock number
  537.         IF r(i).live = 0 AND r(i).explodeFrame = 0 THEN freeRock& = i: EXIT FUNCTION
  538.     NEXT
  539.  
  540. SUB explode (x AS LONG, y AS LONG, r AS LONG, frm AS LONG)
  541.     DIM maxParticles AS LONG, i AS LONG, rounds AS LONG, loopCount AS LONG
  542.     maxParticles = r * 4
  543.     FOR i = 1 TO r
  544.         NewDot i, x, y, r
  545.     NEXT
  546.     rounds = r
  547.     FOR loopCount = 0 TO frm
  548.         IF _KEYDOWN(27) THEN END
  549.         FOR i = 1 TO rounds
  550.             dots(i).x = dots(i).x + dots(i).dx
  551.             dots(i).y = dots(i).y + dots(i).dy
  552.             fcirc dots(i).x, dots(i).y, dots(i).size, dots(i).kolor
  553.         NEXT
  554.         IF rounds < maxParticles THEN
  555.             FOR i = 1 TO r
  556.                 NewDot (rounds + i), x, y, r
  557.             NEXT
  558.             rounds = rounds + r
  559.         END IF
  560.     NEXT
  561.  
  562. SUB NewDot (i AS LONG, x AS LONG, y AS LONG, r AS LONG)
  563.     DIM angle, rd
  564.     angle = pi * 2 * RND
  565.     rd = RND * 30
  566.     dots(i).x = x + rd * COS(angle)
  567.     dots(i).y = y + rd * SIN(angle)
  568.     dots(i).size = RND * r * .05
  569.     rd = RND 'STxAxTIC recommended for rounder spreads
  570.     dots(i).dx = rd * 10 * (10 - 2 * dots(i).size) * COS(angle)
  571.     dots(i).dy = rd * 10 * (10 - 2 * dots(i).size) * SIN(angle)
  572.     rd = 20 + RND * 70
  573.     dots(i).kolor = _RGBA32(rd, rd, rd, 80)
  574.  
  575. SUB drawship 'simple red iso triangle pointed towards radianAngle
  576.     DIM x1 AS LONG, y1 AS LONG, x2 AS LONG, y2 AS LONG, x3 AS LONG, y3 AS LONG
  577.     DIM x4 AS LONG, y4 AS LONG, x5 AS LONG, y5 AS LONG
  578.     IF ship.thrust > 0 THEN
  579.         'burn out flame as thruster dies out
  580.         x4 = ship.x + .5 * ship.thrust * COS(ship.angle - 17 / 18 * pi)
  581.         y4 = ship.y + .5 * ship.thrust * SIN(ship.angle - 17 / 18 * pi)
  582.         x5 = ship.x + .5 * ship.thrust * COS(ship.angle - 19 / 18 * pi)
  583.         y5 = ship.y + .5 * ship.thrust * SIN(ship.angle - 19 / 18 * pi)
  584.         ftri ship.x, ship.y, x4, y4, x5, y5, &H99FFFF88
  585.         ship.thrust = ship.thrust - 1
  586.     END IF
  587.     'draw ship dead or alive thrust or not, calculate 3 points of triangle ship
  588.     fcirc ship.x, ship.y, 30, &H05FFFFFF
  589.     x1 = ship.x + 30 * COS(ship.angle) ' front point
  590.     y1 = ship.y + 30 * SIN(ship.angle) '
  591.     x2 = ship.x + 30 * COS(ship.angle + .6666 * pi) ' wing
  592.     y2 = ship.y + 30 * SIN(ship.angle + .6666 * pi)
  593.     x3 = ship.x + 30 * COS(ship.angle - .6666 * pi) ' other wing
  594.     y3 = ship.y + 30 * SIN(ship.angle - .6666 * pi)
  595.     ftri ship.x, ship.y, x1, y1, x2, y2, _RGB32(80, 120, 80, 80)
  596.     ftri ship.x, ship.y, x1, y1, x3, y3, _RGB32(60, 100, 60, 80)
  597.     LINE (x1, y1)-(ship.x, ship.y), _RGB32(255, 255, 128)
  598.     LINE (x1, y1)-(x2, y2), _RGB32(255, 180, 40)
  599.     LINE (x1, y1)-(x3, y3), _RGB32(255, 180, 40)
  600.  
  601. SUB drawRock (iRock)
  602.     RANDOMIZE USING r(iRock).seed 'this prevents having to save a particular sequence of random number
  603.     DIM dx, dy, j AS LONG, rRad AS SINGLE, leg AS SINGLE, x0 AS LONG, y0 AS LONG, rc AS LONG, c~&, x1 AS LONG, y1 AS LONG, xoff, yoff, i AS LONG
  604.     DIM x2 AS LONG, y2 AS LONG
  605.     dx = r(iRock).speed * COS(r(iRock).heading)
  606.     dy = r(iRock).speed * SIN(r(iRock).heading) 'update location
  607.     r(iRock).ra = r(iRock).ra + r(iRock).spin
  608.     IF r(iRock).x + dx + r(iRock).r < 0 OR r(iRock).x + dx - r(iRock).r > xmax OR r(iRock).y + dy + r(iRock).r < 0 OR r(iRock).y + dy - r(iRock).r > ymax THEN
  609.         IF iRock <= rocks THEN newRock iRock ELSE r(iRock).live = 0
  610.         EXIT SUB ' reassigned get out of here
  611.     ELSE
  612.         r(iRock).x = r(iRock).x + dx
  613.         r(iRock).y = r(iRock).y + dy
  614.     END IF
  615.     FOR j = 10 TO 3 STEP -1 '                  rock drawing (see demo program where developed code)
  616.         rRad = .1 * j * r(iRock).r
  617.         leg = rRad * (RND * .7 + .3)
  618.         x0 = r(iRock).x + leg * COS(r(iRock).ra)
  619.         y0 = r(iRock).y + leg * SIN(r(iRock).ra)
  620.         rc = r(iRock).c + 30 * RND - 15
  621.         c~& = _RGB32(rc + 5, rc - 10, rc + 5)
  622.         x1 = x0
  623.         y1 = y0
  624.         xoff = RND * 20 - 10 + r(iRock).x
  625.         yoff = RND * 20 - 10 + r(iRock).y
  626.         FOR i = 1 TO 12
  627.             leg = rRad * (RND * .35 + .65)
  628.             IF i = 12 THEN
  629.                 x2 = x0: y2 = y0
  630.             ELSE
  631.                 x2 = xoff + leg * COS(i * polyAngle + r(iRock).ra)
  632.                 y2 = yoff + leg * SIN(i * polyAngle + r(iRock).ra)
  633.             END IF
  634.             ftri r(iRock).x, r(iRock).y, x1, y1, x2, y2, c~&
  635.             x1 = x2: y1 = y2
  636.         NEXT
  637.     NEXT
  638.  
  639. SUB newRock (iRock)
  640.     DIM side AS LONG
  641.     RANDOMIZE TIMER * RND 'to avoid making twins
  642.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  643.     SELECT CASE side
  644.         CASE 1
  645.             r(iRock).x = -100
  646.             r(iRock).y = rrnd(20, ymax - 20)
  647.             r(iRock).heading = 3 * pi / 2 + RND * pi
  648.         CASE 2
  649.             r(iRock).x = xmax + 100
  650.             r(iRock).y = rrnd(20, ymax - 20)
  651.             r(iRock).heading = pi / 2 + RND * pi
  652.         CASE 3
  653.             r(iRock).x = rrnd(20, xmax - 20)
  654.             r(iRock).y = -100
  655.             r(iRock).heading = RND * pi
  656.         CASE 4
  657.             r(iRock).x = rrnd(20, xmax - 20)
  658.             r(iRock).y = ymax + 100
  659.             r(iRock).heading = pi + RND * pi
  660.     END SELECT
  661.     r(iRock).speed = rrnd(minRockSpeed, maxRockSpeed) 'speed, rotation angle, radius, gray coloring, spin, seed, hit for explosion
  662.     r(iRock).ra = RND * 2 * pi
  663.     r(iRock).r = irnd&(minRockSize * 3, maxRockSize) 'every parent rock can be split up into at least 2 - 10 size rocks
  664.     r(iRock).c = irnd&(60, 110) ' Ken request increase in rock color
  665.     r(iRock).spin = rrnd(-pi / 20, pi / 20)
  666.     r(iRock).seed = INT(RND * 64000) - 32000
  667.     r(iRock).explodeFrame = 0
  668.     r(iRock).live = 1
  669.  
  670. FUNCTION irnd& (n1, n2) 'return an integer between 2 numbers
  671.     DIM l%, h%
  672.     IF n1 > n2 THEN l% = n2: h% = n1 ELSE l% = n1: h% = n2
  673.     irnd& = INT(RND * (h% - l% + 1)) + l%
  674.  
  675. FUNCTION rrnd (n1, n2) ' return number (expecting reals =_single, double, _float depending on default / define setup)
  676.     rrnd = (n2 - n1) * RND + n1
  677.  
  678. SUB drawBall (x, y, r, c AS _UNSIGNED LONG)
  679.     DIM red AS LONG, grn AS LONG, blu AS LONG, rr AS LONG, f
  680.     red = _RED32(c): grn = _GREEN32(c): blu = _BLUE32(c)
  681.     FOR rr = r TO 0 STEP -1
  682.         f = 1 - rr / r
  683.         fcirc x, y, rr, _RGB32(red * f, grn * f, blu * f)
  684.     NEXT
  685.  
  686. SUB fellipse (CX AS LONG, CY AS LONG, xr AS LONG, yr AS LONG, C AS _UNSIGNED LONG)
  687.     IF xr = 0 OR yr = 0 THEN EXIT SUB
  688.     DIM x AS LONG, y AS LONG
  689.     w2 = xr * xr: h2 = yr * yr: h2w2 = h2 * w2
  690.     LINE (CX - xr, CY)-(CX + xr, CY), C, BF
  691.     DO WHILE y < yr
  692.         y = y + 1
  693.         x = SQR((h2w2 - y * y * w2) \ h2)
  694.         LINE (CX - x, CY + y)-(CX + x, CY + y), C, BF
  695.         LINE (CX - x, CY - y)-(CX + x, CY - y), C, BF
  696.     LOOP
  697.  
  698. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  699.     DIM D AS LONG
  700.     STATIC a&
  701.     D = _DEST
  702.     IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32)
  703.     _DEST a&
  704.     _DONTBLEND a& '  '<<<< new 2019-12-16 fix
  705.     PSET (0, 0), K
  706.     _BLEND a& '<<<< new 2019-12-16 fix
  707.     _DEST D
  708.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  709.  
  710. SUB fcirc (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG) 'vince version
  711.     DIM x0 AS LONG, y0 AS LONG, e AS LONG
  712.     x0 = R: y0 = 0: e = 0
  713.     DO WHILE y0 < x0
  714.         IF e <= 0 THEN
  715.             y0 = y0 + 1
  716.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  717.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  718.             e = e + 2 * y0
  719.         ELSE
  720.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  721.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  722.             x0 = x0 - 1: e = e - 2 * x0
  723.         END IF
  724.     LOOP
  725.     LINE (x - R, y)-(x + R, y), C, BF
  726.