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

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: b+ Asteroids makeover
« Reply #90 on: November 06, 2020, 10:47:33 pm »
I love it B+! I had to dodge the rocks before I got to a 5,000 score this time and since so many more objects are coming out at once now the score goes up faster too! I can't think of anything better. :))) Congratulations!! I also deleted my High Score from the text file so I can start over. :)

Well I got to say it's too much for me. I can't get any where with it now. I can once again blame the crappy arrow keys on my keyboard for part of problem the other is I am too slow :(

BTW I found slightly flawed code in drawStars. I DIM'd the array for 600 stars but use only 200 but why do they look right? Different sizes are moving at different speeds, the stars being replaced correct as they exit stage right and reenter stage left. Because I failed to change the original 200 size and color, just changed x, y to do 600 stars.

So anyway drawStars sub should be this, without the wasted 400 extra stars:
Code: QB64: [Select]
  1. SUB drawStars (moving)
  2.     TYPE starType
  3.         x AS SINGLE
  4.         y AS SINGLE
  5.         size AS SINGLE
  6.         c AS INTEGER
  7.     END TYPE
  8.     STATIC beenHere, stars(200) AS starType, cy AS LONG
  9.     DIM i AS LONG
  10.     IF beenHere = 0 THEN 'static part
  11.         FOR i = 0 TO 100
  12.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = .3
  13.             stars(i).c = irnd&(80, 140)
  14.         NEXT
  15.         FOR i = 101 TO 150
  16.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = .6
  17.             stars(i).c = irnd&(110, 170)
  18.         NEXT
  19.         FOR i = 151 TO 195
  20.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = 1.2
  21.             stars(i).c = irnd&(140, 200)
  22.         NEXT
  23.         FOR i = 196 TO 200
  24.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = 2.4
  25.             stars(i).c = irnd&(170, 235)
  26.         NEXT
  27.         cy = ymax / 2
  28.         beenHere = 1
  29.     END IF
  30.     FOR i = 0 TO cy
  31.         LINE (0, i)-(xmax, i), _RGB32(0, 0, .1 * i + 4)
  32.         LINE (0, ymax - i)-(xmax, ymax - i), _RGB(0, 0, .1 * i + 4)
  33.     NEXT
  34.     FOR i = 0 TO 200
  35.         IF moving THEN
  36.             stars(i).x = stars(i).x + .2 * stars(i).size ^ stars(i).size
  37.             IF stars(i).x > xmax THEN stars(i).x = -1 * RND * 20
  38.         END IF
  39.         fcirc stars(i).x, stars(i).y, stars(i).size, _RGB32(stars(i).c - 10, stars(i).c, stars(i).c + 10)
  40.     NEXT
  41.  

Offline bplus

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

Record score 148,000+ allot less frustrating than keys and they still work.

So Dav's flashlight has nothing over my mouse for pilot ;-))

EDIT Update 2020-11-08: Dav caught a conflict in ship moving when mouse was employed at start of game. OK so I added a mouseMode that checks if we are doing all keys moving of ship in which case thrust and hyperdrive keys will work; otherwise, in mouseMode, the thrust and hyperdrive are disabled.
« Last Edit: November 08, 2020, 09:11:16 pm by bplus »

Offline Dav

  • Forum Resident
  • Posts: 792
Re: b+ Asteroids makeover
« Reply #92 on: November 08, 2020, 07:24:16 pm »
Woah - sure is more challenging after pressing m!  I'll have to work hard to beat your score!  I kind of like using the mouse now.  For some reason I can't get thrust to thrust.   Pressing up arrow or k will draw the thrusting graphics, but the ships doesn't move for me. 

- Dav

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: b+ Asteroids makeover
« Reply #93 on: November 08, 2020, 08:03:31 pm »
Woah - sure is more challenging after pressing m!  I'll have to work hard to beat your score!  I kind of like using the mouse now.  For some reason I can't get thrust to thrust.   Pressing up arrow or k will draw the thrusting graphics, but the ships doesn't move for me. 

- Dav

Thrust and also hyperdrive don't always work on first key press. It's another boring problem about clearing or over clearing key presses? The mouse was taking over the positioning of the ship as would be expected.

But you know what? I like the mouse way better although hyperdrive does come in handy (when it works). My arrow keys on my keyboard are a sin against gamers.

Did I mention left and right mouse buttons swing the guns left or right?

Wait, you say you see graphics but no thrust changing of position? I will look into that.
Edit Update 2020-11-08: OK thrust and hyperdrive keys are disabled while in mouseMode.
« Last Edit: November 08, 2020, 09:18:19 pm by bplus »

Offline Kiara87

  • Forum Regular
  • Posts: 164
Re: b+ Asteroids makeover
« Reply #94 on: November 08, 2020, 08:14:24 pm »
nice game congratulations

i was also looking for the tangram game for QB64 but i didn't find it
se avessi solo un'ora per salvare il mondo, passerei 55 minuti per definire bene il problema e 5 a trovare la soluzione

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: b+ Asteroids makeover
« Reply #95 on: November 08, 2020, 08:19:51 pm »
nice game congratulations

i was also looking for the tangram game for QB64 but i didn't find it

The Tangram Game https://www.google.com/search?q=tangram+game&client=opera&hs=Dde&sxsrf=ALeKk0395sUgEmZSxUXqd4EDrIEkoDcZUA:1604884559689&source=lnms&tbm=isch&sa=X&ved=2ahUKEwiWo9fwpPTsAhVJVc0KHUx-BHcQ_AUoAnoECAUQBA&biw=1179&bih=606

I never seen one either in QB64 or any other code. Looks interesting.

Offline Kiara87

  • Forum Regular
  • Posts: 164
Re: b+ Asteroids makeover
« Reply #96 on: November 08, 2020, 08:29:02 pm »
The Tangram Game https://www.google.com/search?q=tangram+game&client=opera&hs=Dde&sxsrf=ALeKk0395sUgEmZSxUXqd4EDrIEkoDcZUA:1604884559689&source=lnms&tbm=isch&sa=X&ved=2ahUKEwiWo9fwpPTsAhVJVc0KHUx-BHcQ_AUoAnoECAUQBA&biw=1179&bih=606

I never seen one either in QB64 or any other code. Looks interesting.

yes it is a Chinese puzzle

to a nice story about the Buddhist monks giving this tangram to a little boy

and with this tangram he can create anything like how programmers create any program


https://www.navediclo.it/webapp/tangram/tangram.html

online you can play there are several sources

also app for android

missing only for QB64
se avessi solo un'ora per salvare il mondo, passerei 55 minuti per definire bene il problema e 5 a trovare la soluzione

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: b+ Asteroids makeover
« Reply #97 on: November 08, 2020, 09:15:54 pm »
OK the code in Best Answer for Asteroids has been updated with a mouseMode variable you can set while seeing the splash screen at the beginning. If you press m for mouseMode, the thrust and hyperdrive keys will be disabled and the ship will move with the mouse, otherwise the up arrow or K key will offer the thrust option and the Enter key or space bar the hyperdrive option.

Thanks @Dav  for the heads up!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: b+ Asteroids makeover
« Reply #98 on: March 30, 2021, 06:20:17 pm »
Oh man, this game seems so much easier since last I played it!?

Left mouse button shoots left, right shoots right, mostly it's Dodge Ball.

Update: Oh, I see what happened I copied code here and played so my high score was stored in QB64 folder not my old Asteroid folder, my high score there was double this one.

Oh I don't remember my game so well, I had 9 more lives to play :-))
New High Score.PNG
* New High Score.PNG (Filesize: 79.77 KB, Dimensions: 1359x760, Views: 88)
« Last Edit: April 02, 2021, 03:05:57 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: b+ Asteroids makeover
« Reply #99 on: April 01, 2021, 01:07:53 pm »
Here is the type of shooter I had desired to install in Asteroids (though the left and right mouse button ones are pretty good, this is what I wanted from start):
Code: QB64: [Select]
  1. _Title "Mouse Action Shooter - Jerk fix attempt" 'B+ rev 2021-04-01
  2. 'Mouse Action Shooter started from eRATication 5 by bplus 2018-08-06"
  3. ' upodate Mouse Action Shooter with MB triggers 2019-04-01
  4. ' 2019-04-03 add some targets for practice
  5.  
  6. ' SCORE System:
  7. ' Right click to fire a bullet, they cost 10 points each.
  8. ' Targets range from 30 for biggest targets to 100 points for smallest Targets
  9. ' Get hit by target loose 100 points and delay of game.
  10.  
  11. '2019-04-04 Keeping Ashish Target fix, wait until completely off screen.
  12. ' Now give the bullets a little long range before deactivating them.
  13. ' Fix shooter x, y by locating in center of shooter instead of nose. It's already OK!
  14.  
  15. ' 2021-03-19 using this code for oh program and want to fix point when target crashes into shooter/ship
  16. ' by reassignning target new coordinates by saying NewTarget index that should fix the continuous crashing right?
  17. ' Let's see, in oh it doesn't work, how about here?  Works just as expected. So what's up with oh?
  18. ' (Fixed it was an index goof for public variables used in GoSubs).
  19.  
  20. ' 2021-03-31 try to incorparate MasterGy jerky fix when moving shooter/ship around in tight circles or spin.
  21. ' 2021-04-01 Thanks to MasterGy who proved it possible to make a stready shooter with _ATAN2 mouse position
  22. ' alone (with previous position). I redoubled my efforts and came up with slightly different method.
  23.  
  24. 'screen dimensions
  25. Const xmax = 1200
  26. Const ymax = 700
  27. Const nBullets = 15
  28. Const bSpeed = 30
  29. Const nTargets = 3 'should probably depend on level of play
  30. Const tSpeed = 5 'should probably depend on level of play
  31. Const shooterRadius = 50
  32.  
  33. Type shooterType
  34.     x As Single
  35.     y As Single
  36.     a As Single
  37.  
  38. Type bulletType
  39.     x As Integer
  40.     y As Integer
  41.     dx As Integer
  42.     dy As Integer
  43.     live As Integer
  44.  
  45. Type targetType
  46.     x As Single
  47.     y As Single
  48.     a As Single
  49.     r As Integer
  50.  
  51. Screen _NewImage(xmax, ymax, 32)
  52. _ScreenMove 100, 20
  53.  
  54.  
  55. Dim Shared GameOn, mb1, last1, score
  56.  
  57. 'targets
  58. Dim Shared t(nTargets - 1) As targetType
  59. For i = 0 To nTargets - 1: newTarget i: Next
  60.  
  61. 'bullets
  62. Dim Shared b(nBullets - 1) As bulletType
  63.  
  64. 'shooter
  65. Dim Shared shooter As shooterType
  66. shooter.x = xmax / 2
  67. shooter.y = ymax / 2
  68. shooter.a = 0
  69. lastx = xmax / 2: lasty = ymax / 2
  70.  
  71. 'game
  72. GameOn = 1
  73. While GameOn
  74.     Cls
  75.     _Title "Target Practice   Score:" + Str$(score)
  76.     mb1 = 0: mb2 = 0
  77.     shooter.x = _MouseX: shooter.y = _MouseY
  78.     If Abs(shooter.y - lasty) > 0 Or Abs(shooter.x - lastx) > 0 Then 'shooter has moved
  79.         test = _Atan2(shooter.y - lasty, shooter.x - lastx) ' radian angle between -pi and pi
  80.         diff# = PositiveRA#(PositiveRA#(shooter.a) - PositiveRA#(test)) ' convert angles to positive numbers then convert difference to positive number
  81.         ' the angle of shooter is extremely sensitive to change when you press mouse button it often jerks bullet off target so
  82.         ' dampen the newest read of mouse position (test) and convert to angle we can subtract and convert back.
  83.         shooter.a = shooter.a - .2 * PlusMinusPiRA#(diff#) ' convert difference back to -pi to p1 number and dampen change by .1 to .4
  84.         lastx = shooter.x: lasty = shooter.y
  85.     End If
  86.  
  87.     t = Timer(.001)
  88.     If _MouseButton(1) Then 'when ship is heading north the left button should be left
  89.         If t - last1 > .3 Then mb1 = 1: last1 = t
  90.     End If
  91.     handleTargets
  92.     drawshooter
  93.     handleBullets
  94.     _Display
  95.     _Limit 60
  96.  
  97. Sub handleTargets
  98.     For i = 0 To nTargets - 1
  99.         'update position
  100.         t(i).x = t(i).x + tSpeed * Cos(t(i).a)
  101.         t(i).y = t(i).y + tSpeed * Sin(t(i).a)
  102.         'inbounds?
  103.         If t(i).x < -shooterRadius Or t(i).x > xmax + shooterRadius Or t(i).y < -shooterRadius Or t(i).y > ymax + shooterradiu Then
  104.             newTarget i
  105.         Else
  106.             If hitShooter(i) Then 'now I discovered in oh program this continues to crash and deduct 100 until target moves through shooter
  107.                 'explosion
  108.                 Cls
  109.                 _PrintString (xmax / 2 - 40, ymax / 2 - 10), "Bang!... Ouch!"
  110.                 score = score - 100
  111.                 _Display
  112.                 _Delay .2
  113.                 ' fix target crashing into ship by removing target with reassigning
  114.                 newTarget i ' in oh this does not work
  115.             Else
  116.                 drawTarget i
  117.             End If
  118.         End If
  119.     Next
  120.  
  121. Sub newTarget (i)
  122.     'pick edge
  123.     edge = Int(Rnd * 4)
  124.     Select Case edge
  125.         Case 0: t(i).x = -shooterRadius: t(i).y = Rnd * (ymax - 300) + 150: t(i).a = Rnd * _Pi
  126.         Case 1: t(i).x = xmax + shooterRadius: t(i).y = Rnd * (ymax - 300) + 150: t(i).a = _Pi / 2 + Rnd * _Pi
  127.         Case 2: t(i).x = Rnd * xmax: t(i).y = -shooterRadius: t(i).a = Rnd * _Pi
  128.         Case 3: t(i).x = Rnd * xmax: t(i).y = ymax + shooterRadius: t(i).a = _Pi + Rnd * _Pi
  129.     End Select
  130.     t(i).r = (Int(Rnd * 8) + 3) * 10 '30 to 100 score 130 - radius 100 to 30
  131.  
  132. Sub drawTarget (i)
  133.     For r = t(i).r To 0 Step -t(i).r / 10
  134.         count = (count + 1) Mod 2
  135.         If count Then c~& = _RGB32(255, 0, 0) Else c~& = _RGB32(255, 255, 255)
  136.         fcirc t(i).x, t(i).y, r, c~&
  137.     Next
  138.  
  139. Sub handleBullets ()
  140.     For i = 0 To nBullets - 1
  141.         If b(i).live = 0 And mb1 = 1 Then 'have in active bullet index to use
  142.             b(i).x = shooter.x + .5 * shooterRadius * Cos(shooter.a)
  143.             b(i).y = shooter.y + .5 * shooterRadius * Sin(shooter.a)
  144.             b(i).dx = bSpeed * Cos(shooter.a)
  145.             b(i).dy = bSpeed * Sin(shooter.a)
  146.             b(i).live = 1
  147.             mb1 = 0
  148.             score = score - 10 'bullets cost 10 points
  149.  
  150.         ElseIf b(i).live = 1 Then 'new location
  151.             b(i).x = b(i).x + b(i).dx
  152.             b(i).y = b(i).y + b(i).dy
  153.             If b(i).x > -50 And b(i).x < xmax + 50 And b(i).y > -50 And b(i).y < ymax + 50 Then 'in bounds draw it
  154.                 'check for collision with ...
  155.                 t = hitTarget(i)
  156.                 If t > -1 Then
  157.                     score = score + 130 - t(t).r
  158.                     b(i).live = 0
  159.                     newTarget t
  160.                 Else
  161.                     'draw bullet
  162.                     ba = _Atan2(b(i).dy, b(i).dx): b = 15
  163.                     x1 = b(i).x + b * Cos(ba)
  164.                     y1 = b(i).y + b * Sin(ba)
  165.                     x2 = b(i).x + b * Cos(ba + _Pi(5 / 6))
  166.                     y2 = b(i).y + b * Sin(ba + _Pi(5 / 6))
  167.                     x3 = b(i).x + b * Cos(ba + _Pi(7 / 6))
  168.                     y3 = b(i).y + b * Sin(ba + _Pi(7 / 6))
  169.                     fTri x1, y1, x2, y2, x3, y3, _RGB32(10, 160, 160)
  170.                     'fcirc b(i).x, b(i).y, 4, _RGB32(64, 0, 0)
  171.                 End If
  172.             Else
  173.                 b(i).live = 0 'dectiveate
  174.             End If
  175.         End If
  176.     Next
  177.  
  178. Function hitTarget (bulletIndex)
  179.     hitTarget = -1
  180.     For i = 0 To nTargets - 1
  181.         If Sqr((t(i).x - b(bulletIndex).x) ^ 2 + (t(i).y - b(bulletIndex).y) ^ 2) <= t(i).r Then hitTarget = i: Exit Function
  182.     Next
  183.  
  184. Function hitShooter (TargetIndex)
  185.     If Sqr((shooter.x - t(TargetIndex).x) ^ 2 + (shooter.y - t(TargetIndex).y) ^ 2) <= t(i).r Then hitShooter = 1: Exit Function
  186.  
  187. Sub drawshooter ()
  188.     x1 = shooter.x + (shooterRadius - 30) * Cos(shooter.a)
  189.     y1 = shooter.y + (shooterRadius - 30) * Sin(shooter.a)
  190.     x2 = shooter.x + (shooterRadius + 20) * Cos(shooter.a + _Pi(11 / 16))
  191.     y2 = shooter.y + (shooterRadius + 20) * Sin(shooter.a + _Pi(11 / 16))
  192.     x3 = shooter.x + (shooterRadius + 20) * Cos(shooter.a - _Pi(11 / 16))
  193.     y3 = shooter.y + (shooterRadius + 20) * Sin(shooter.a - _Pi(11 / 16))
  194.     fTri x1, y1, x2, y2, x3, y3, _RGB32(85, 45, 0)
  195.     x1 = shooter.x + shooterRadius * Cos(shooter.a)
  196.     y1 = shooter.y + shooterRadius * Sin(shooter.a)
  197.     x2 = shooter.x + shooterRadius * Cos(shooter.a + _Pi(7 / 8))
  198.     y2 = shooter.y + shooterRadius * Sin(shooter.a + _Pi(7 / 8))
  199.     x3 = shooter.x + shooterRadius * Cos(shooter.a - _Pi(7 / 8))
  200.     y3 = shooter.y + shooterRadius * Sin(shooter.a - _Pi(7 / 8))
  201.     fTri x1, y1, x2, y2, x3, y3, _RGB32(0, 0, 200)
  202.     x2 = shooter.x + shooterRadius * Cos(shooter.a + _Pi(15 / 16))
  203.     y2 = shooter.y + shooterRadius * Sin(shooter.a + _Pi(15 / 16))
  204.     x3 = shooter.x + shooterRadius * Cos(shooter.a - _Pi(15 / 16))
  205.     y3 = shooter.y + shooterRadius * Sin(shooter.a - _Pi(15 / 16))
  206.     fTri x1, y1, x2, y2, x3, y3, _RGB32(255, 255, 255)
  207.  
  208.     'check shooter x, y  = fixed a long time ago!
  209.     'fcirc shooter.x, shooter.y, 4, _RGB32(140, 120, 140)
  210.  
  211. ' found at [abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]:    http://www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]/forum/index.php?topic=14425.0
  212. Sub fTri (x1, y1, x2, y2, x3, y3, K As _Unsigned Long)
  213.     a& = _NewImage(1, 1, 32)
  214.     _Dest a&
  215.     PSet (0, 0), K
  216.     _Dest 0
  217.     _MapTriangle _Seamless(0, 0)-(0, 0)-(0, 0), a& To(x1, y1)-(x2, y2)-(x3, y3)
  218.     _FreeImage a& '<<< this is important!
  219.  
  220. Sub fcirc (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
  221.     Dim Radius As Integer, RadiusError As Integer
  222.     Dim X As Integer, Y As Integer
  223.  
  224.     Radius = Abs(R)
  225.     RadiusError = -Radius
  226.     X = Radius
  227.     Y = 0
  228.  
  229.     If Radius = 0 Then PSet (CX, CY), C: Exit Sub
  230.  
  231.     ' Draw the middle span here so we don't draw it twice in the main loop,
  232.     ' which would be a problem with blending turned on.
  233.     Line (CX - X, CY)-(CX + X, CY), C, BF
  234.  
  235.     While X > Y
  236.         RadiusError = RadiusError + Y * 2 + 1
  237.         If RadiusError >= 0 Then
  238.             If X <> Y + 1 Then
  239.                 Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  240.                 Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  241.             End If
  242.             X = X - 1
  243.             RadiusError = RadiusError - X * 2
  244.         End If
  245.         Y = Y + 1
  246.         Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  247.         Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  248.     Wend
  249.  
  250. 'convert output of _ATAN2 to positive Radian Angle
  251. Function PositiveRA# (ra As Double) ' having trouble comparing angles returned from _ATAN2
  252.     raa = ra ' dont change ra here
  253.     While raa < 0
  254.         raa = raa + 6.283185307179586
  255.     Wend
  256.     While raa > _Pi(2)
  257.         raa = raa - 6.283185307179586
  258.     Wend
  259.     PositiveRA# = raa
  260.  
  261. 'convert Positive Radian Angle back to Radian Angle between -pi and pi
  262. Function PlusMinusPiRA# (ra As Double)
  263.     raa = ra ' dont change ra here
  264.     While raa < -3.141592653589793
  265.         raa = raa + 6.283185307179586
  266.     Wend
  267.     While raa > 3.141592653589793
  268.         raa = raa - 6.283185307179586
  269.     Wend
  270.     PlusMinusPiRA# = raa
  271.  

I have commented critical change in finding shooter angle above and tested with faster targets and more pause between bullets (so you can't machine gun targets down).

Hope to install this new method into new version of Asteroids here.

Offline MasterGy

  • Seasoned Forum Regular
  • Posts: 327
  • people lie, math never lies
Re: b+ Asteroids makeover
« Reply #100 on: April 01, 2021, 02:02:47 pm »
works nice! good luck for that !

Marked as best answer by bplus on April 03, 2021, 06:51:45 pm

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: b+ Asteroids makeover
« Reply #101 on: April 03, 2021, 10:29:21 pm »
b+QB64 Asteroids - MAS version
Code: QB64: [Select]
  1. _Title "b+QB64 Asteroids - MAS" 'started 2018-07-13 rev 2021-04-03 MAS (Mouse Action Shooter)
  2. '2020 - Oct and Nov: Special thanks to SierraKen who has been helpful with suggestions, ideas and fixes.
  3. ' 2021-04-04 from b+QB64 - M10 version that had mouse left and right shooter off mouse buttons.
  4. ' This version - MAS:
  5. ' MAS stands for Mouse Action Shooter, the ship/shooter points according to current and last mouse
  6. ' position, bullets are constantly fired forward. You'd wear out your fingers if you constantly had
  7. ' to use spacebar or mousebutton to fire.
  8.  
  9.  
  10. ' Far far away in a universe where Newton's 1st Law of Motion is not obeyed...    ;-))
  11.  
  12.  
  13. ' points:
  14. ' The higher the speed the better    speed range .5 to 2.5, diff = 2 * 50 = 100          s - .5 * 50
  15. ' The smaller the size the better  size range 10 to 100, diff = 90 * 1.1111 = 100  90 - (sz -10) * 1.1111
  16. '        ((speed - .5) * 50 + (90 - (r - 10)) * 1.1111) / 2 = 100 best score per hit
  17. '================================================================================================================
  18.  
  19. '    NOTE: !!!!!!!!!!!!!!!   When there is a pause in action, just press enter,  as in enter a new life!
  20.  
  21. '================================================================================================================
  22.  
  23. Const xmax = 1200, ymax = 700, pi = _Pi, polyAngle = _Pi / 6, nRocks = 300, nBullets = 2000, bSpeed = 15
  24. Const minRockSpeed = 0.7500, maxRockSpeed = 3.2500, minRockSize = 10, maxRockSize = 100
  25. Const rockSpeedRange = maxRockSpeed - minRockSpeed, rockSizeRange = maxRockSize - minRockSize
  26. Const alienSpeed = rockSpeedRange / 2 + minRockSpeed ' average rock speed
  27.  
  28. Type alienType
  29.     x As Single
  30.     y As Single
  31.     dx As Single
  32.     dy As Single
  33.     ls As Long ' lights offset and gray scale
  34.     c As _Unsigned Long ' color
  35.     live As Long
  36.     attackFrame As Long
  37.     fireX As Single
  38.     fireY As Single
  39.     transform As Long
  40.  
  41. Type particle
  42.     x As Single
  43.     y As Single
  44.     dx As Single
  45.     dy As Single
  46.     size As Single
  47.     kolor As _Unsigned Long
  48.  
  49. Type bullet
  50.     x As Single
  51.     y As Single
  52.     dx As Single
  53.     dy As Single
  54.     live As Long
  55.  
  56. Type shipType
  57.     x As Single
  58.     y As Single
  59.     live As Long
  60.     speed As Single '       just a constant now when Thrust is applied
  61.     angle As Single '       rotated position ship/gun now A or S keypress or hold down
  62.  
  63. Type rock
  64.     x As Single
  65.     y As Single
  66.     r As Long '            radius
  67.     ra As Single '         rotation position   a = a + spin
  68.     heading As Single '    heading from which dx, dy are calc with speed
  69.     speed As Single '      speed
  70.     spin As Single '       rotation direction and amount
  71.     seed As Long '         for drawing rocks with RND USING
  72.     c As Long '            color   rgb(c, c, c)
  73.     live As Long '         need this to track rocks still active like bullets
  74.     explodeFrame As Long ' after a rock is hit by bullet, it explodes and in more than one frame
  75.  
  76. ReDim Shared aliens(1 To 5) As alienType
  77. ReDim Shared BolderOfDeathSpeed
  78. Dim Shared dots(2000) As particle ' explosions
  79. Dim Shared b(nBullets) As bullet
  80. Dim Shared ship As shipType
  81. Dim Shared r(nRocks) As rock
  82. Dim Shared points As Long
  83. 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
  84.  
  85. Dim HS As Long, fnt As Long, fnt2 As Long ' file LOAD handles
  86. Dim As Long lastx, lasty ' mouse = ship/shooter location at last poll
  87. Dim As Double diff, test ' deciding the new ship/shooter angle MAS system
  88. Dim i As Long, bullets As Long, fire As Long ' index and bullets
  89. Dim r As Long, newRockN As Long, maxBabyRocks As Long, br As Long, hits As Long ' rock stuff
  90. Dim ai As Long, alienN As Long ' alien index and number
  91. Dim kh As Long 'key hit for pause
  92. Dim hs$, s$, k$, t, lastt 'high score, general string and times for bullets
  93. Dim rockPoints As Long, roundPoints As Long ' various points scores
  94.  
  95. Screen _NewImage(xmax, ymax, 32)
  96. _ScreenMove 100, 20
  97. _FullScreen '<<<<<<<< optional
  98.  
  99. fnt = _LoadFont("ARLRDBD.ttf", 16, "MONOSPACE")
  100. fnt2 = _LoadFont("ARLRDBD.ttf", 40, "MONOSPACE")
  101. _Font fnt2
  102. Color &HFF00FFFF, &H00000000
  103.  
  104. If _FileExists("Asteroids High Score.txt") Then
  105.     Open "Asteroids High Score.txt" For Input As #1
  106.     Input #1, HS
  107.     Close #1
  108. hs$ = "High Score:" + Str$(HS)
  109.  
  110. 'a little splash screen
  111. rocks = 7: alienN = 3
  112. For i = 1 To nRocks
  113.     newRock i
  114.     If i > rocks Then r(i).live = 0
  115. For i = 1 To alienN
  116.     newAlien i
  117. i = 0
  118. ship.x = xmax / 2 'avoids explosions top left corner at start, dang still get some!
  119. ship.y = ymax / 2
  120. lastx = ship.x
  121. lasty = ship.y
  122. BolderOfDeathSpeed = 2.5
  123.     drawStars 0
  124.     i = i + 1
  125.     If i Mod 30 = 29 And rocks < nRocks Then rocks = rocks + 1: r(rocks).live = 1
  126.     For r = 1 To nRocks
  127.         If r(r).live Then DrawRock r
  128.     Next
  129.     For i = 1 To alienN
  130.         drawAliens i
  131.     Next
  132.     While _MouseInput: Wend ' ship positioning and angle from current mouse and last mouse position
  133.     ship.x = _MouseX: ship.y = _MouseY
  134.     If Abs(ship.y - lasty) > 0 Or Abs(ship.x - lastx) > 0 Then 'shooter has moved
  135.         test = _Atan2(ship.y - lasty, ship.x - lastx) ' radian angle between -pi and pi
  136.         diff = PositiveRA#(PositiveRA#(ship.angle) - PositiveRA#(test)) ' convert angles to positive numbers then convert difference to positive number
  137.         ' the angle of shooter is extremely sensitive to change when you press mouse button it often jerks bullet off target so
  138.         ' dampen the newest read of mouse position (test) and convert to angle we can subtract and convert back.
  139.         ship.angle = ship.angle - .2 * PlusMinusPiRA#(diff#) ' convert difference back to -pi to p1 number and dampen change by .1 to .4
  140.         lastx = ship.x: lasty = ship.y
  141.     End If
  142.     DrawShip
  143.     _Font fnt2
  144.     Color &HFFFF0000
  145.     s$ = "*** b+QB64 Asteroids - MAS ***"
  146.     _PrintString ((_Width - _PrintWidth(s$)) / 2 + 3, 150 + 3), s$
  147.     _PrintString ((_Width - _PrintWidth(hs$)) / 2 + 3, 300 + 3), hs$
  148.     s$ = "p to pause action"
  149.     _PrintString ((_Width - _PrintWidth(s$)) / 2 + 3, 400 + 3), s$
  150.     s$ = "p again to restart action"
  151.     _PrintString ((_Width - _PrintWidth(s$)) / 2 + 3, 450 + 3), s$
  152.     s$ = "OK press any to start"
  153.     _PrintString ((_Width - _PrintWidth(s$)) / 2 + 3, 550 + 3), s$
  154.     Color &HFFFFBBBB
  155.     s$ = "*** b+QB64 Asteroids - MAS ***"
  156.     _PrintString ((_Width - _PrintWidth(s$)) / 2, 150), s$
  157.     _PrintString ((_Width - _PrintWidth(hs$)) / 2, 300), hs$
  158.     s$ = "p to pause action"
  159.     _PrintString ((_Width - _PrintWidth(s$)) / 2, 400), s$
  160.     s$ = "p again to restart action"
  161.     _PrintString ((_Width - _PrintWidth(s$)) / 2, 450), s$
  162.     s$ = "OK press any to start"
  163.     _PrintString ((_Width - _PrintWidth(s$)) / 2, 550), s$
  164.  
  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 = 3: rocks = 5 ' always active rocks
  177. points = 0: hits = 0: bullets = 0
  178. BolderOfDeathSpeed = 2.5
  179. While lives > 0 And _KeyDown(27) = 0 ' init start restart
  180.     ReDim aliens(1 To alienN) As alienType
  181.     For ai = 1 To alienN
  182.         newAlien ai
  183.     Next
  184.     For i = 1 To nRocks 'reset rocks mainly clear baby rocks
  185.         newRock (i)
  186.         If i > rocks Then r(i).live = 0
  187.     Next
  188.     ship.x = xmax / 2 'avoids explosions top left corner at start, dang still get some!
  189.     ship.y = ymax / 2
  190.     lastx = ship.x
  191.     lasty = ship.y
  192.     ship.angle = 0
  193.     ship.live = 1
  194.     rockPoints = 0
  195.     roundPoints = 0
  196.     While ship.live And _KeyDown(27) = 0
  197.  
  198.         'draw everything then process bullets
  199.         drawStars 1
  200.         Locate 1, 1: Print "Lives:"; lives
  201.         Locate 2, 1: Print "Last Rock:"; Str$(rockPoints)
  202.         Locate 3, 1: Print "Round:;"; Str$(roundPoints)
  203.         Locate 4, 1: Print "Points:"; Str$(points)
  204.         Locate 5, 1: Print "High Score:"; Str$(HS)
  205.         For ai = 1 To alienN
  206.             drawAliens ai
  207.         Next
  208.         For i = 1 To nRocks
  209.             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
  210.                 DrawRock i ' while drawing rocks the ship could be blown up
  211.                 If ((r(i).x - ship.x) ^ 2 + (r(i).y - ship.y) ^ 2) ^ .5 < r(i).r + 20 Then 'rock collides with ship?
  212.                     For br = 1 To 200 Step 5
  213.                         Circle ((ship.x + r(i).x) / 2, (ship.y + r(i).y) / 2), br, _RGB32(255 - br, 255 - 2 * br, 0)
  214.                     Next
  215.                     DrawRock i
  216.                     DrawShip
  217.                     ship.live = 0
  218.                     If i <= rocks Then newRock i Else r(i).live = 0
  219.                 End If
  220.             End If
  221.         Next
  222.         For i = 1 To nRocks 'smoke up the place with rock debris fields still flying out from hit frames ago
  223.             If r(i).explodeFrame Then
  224.                 r(i).explodeFrame = r(i).explodeFrame + 1
  225.                 If r(i).explodeFrame > .25 * r(i).r Then
  226.                     r(i).explodeFrame = 0
  227.                     If i <= rocks Then newRock i ' now replace the rock
  228.                 Else
  229.                     explode r(i).x, r(i).y, r(i).r, r(i).explodeFrame
  230.                 End If
  231.             End If
  232.         Next
  233.         If ship.live Then
  234.             For ai = 1 To alienN
  235.                 If Sqr((aliens(ai).x - ship.x) ^ 2 + (aliens(ai).y - ship.y) ^ 2) < 55 Then 'aliens and ship collisde boom boom
  236.                     For br = 1 To 200 Step 5
  237.                         Circle ((ship.x + aliens(ai).x) / 2, (ship.y + aliens(ai).y) / 2), br, _RGB32(255 - br, 255 - 2 * br, 0)
  238.                     Next
  239.                     DrawShip
  240.                     ship.live = 0
  241.                     _Continue
  242.                 Else
  243.                     DrawShip
  244.                 End If
  245.             Next
  246.             '  ============= MAS Mouse Action Shooter System
  247.             While _MouseInput: Wend ' ship positioning and angle from current mouse and last mouse position
  248.             ship.x = _MouseX: ship.y = _MouseY
  249.             If Abs(ship.y - lasty) > 0 Or Abs(ship.x - lastx) > 0 Then 'shooter has moved
  250.                 test = _Atan2(ship.y - lasty, ship.x - lastx) ' radian angle between -pi and pi
  251.                 diff = PositiveRA#(PositiveRA#(ship.angle) - PositiveRA#(test)) ' convert angles to positive numbers then convert difference to positive number
  252.                 ' the angle of shooter is extremely sensitive to change when you press mouse button it often jerks bullet off target so
  253.                 ' dampen the newest read of mouse position (test) and convert to angle we can subtract and convert back.
  254.                 ship.angle = ship.angle - .2 * PlusMinusPiRA#(diff#) ' convert difference back to -pi to p1 number and dampen change by .1 to .4
  255.                 lastx = ship.x: lasty = ship.y
  256.             End If
  257.  
  258.             fire = 0
  259.             t = Timer(.01)
  260.             If lastt = 0 Or t - lastt > .15 Then fire = 1: Sound 2088, .01: lastt = t
  261.  
  262.             kh = _KeyHit
  263.             Select Case kh
  264.                 Case 112 ' p for pause
  265.                     kh = 0
  266.                     While _KeyHit <> 112: _Limit 60: Wend
  267.             End Select
  268.  
  269.             For i = 0 To nBullets '                                               handle bullets
  270.                 If b(i).live = 0 And fire = 1 Then 'have inactive bullet to use
  271.                     b(i).x = ship.x + 2 * bSpeed * Cos(ship.angle)
  272.                     b(i).y = ship.y + 2 * bSpeed * Sin(ship.angle)
  273.                     b(i).dx = bSpeed * Cos(ship.angle)
  274.                     b(i).dy = bSpeed * Sin(ship.angle)
  275.                     b(i).live = -1
  276.                     bullets = bullets + 1
  277.                     fire = 0
  278.                 End If
  279.                 If b(i).live Then 'new location
  280.                     b(i).x = b(i).x + b(i).dx
  281.                     b(i).y = b(i).y + b(i).dy
  282.                     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
  283.  
  284.                         'bullet hit aliens?
  285.                         For ai = 1 To alienN
  286.                             If Sqr((aliens(ai).x - b(i).x) ^ 2 + (aliens(ai).y - b(i).y) ^ 2) < 30 Then
  287.                                 For br = 1 To 120
  288.                                     Circle (aliens(ai).x, aliens(ai).y), br / 3, plasma~&(0)
  289.                                 Next
  290.                                 _Display
  291.                                 _Delay .05
  292.                                 hits = hits + 1
  293.                                 roundPoints = roundPoints + 100
  294.                                 points = points + 100
  295.                                 aliens(ai).live = 0
  296.                                 newAlien ai
  297.                                 b(i).live = 0
  298.                                 _Continue
  299.                             End If
  300.                         Next
  301.                         For r = 1 To nRocks 'check for collision with rock
  302.                             If r(r).live Then
  303.                                 If Sqr((r(r).x - b(i).x) ^ 2 + (r(r).y - b(i).y) ^ 2) < r(r).r Then 'its a hit!
  304.                                     r(r).explodeFrame = 1 'linger with explosion
  305.                                     r(r).live = 0
  306.                                     hits = hits + 1
  307.                                     rockPoints = 50 * ((r(r).speed - minRockSpeed) / rockSpeedRange + (rockSizeRange - (r(r).r - minRockSize)) / rockSizeRange)
  308.                                     roundPoints = roundPoints + rockPoints
  309.                                     points = points + rockPoints
  310.                                     If r(r).r > 30 Then '       split rock  into ? new ones
  311.                                         maxBabyRocks = Int((r(r).r - 10) / 10)
  312.                                         maxBabyRocks = irnd&(2, maxBabyRocks) ' pick a number of baby Rocks
  313.                                         For br = 1 To maxBabyRocks
  314.                                             '                        new rock
  315.                                             newRockN = freeRock& '                          get inactive rock number
  316.                                             newRock newRockN '                              new identity and activate
  317.                                             r(newRockN).r = (r(r).r - 10) / maxBabyRocks '  split in equal parts minus 20% mass
  318.                                             r(newRockN).x = r(r).x + irnd&(-30, 30) '       thrown from parent
  319.                                             r(newRockN).y = r(r).y + irnd&(-30, 30)
  320.                                             r(newRockN).c = r(r).c '                   same color as parent
  321.                                             r(newRockN).heading = rrnd(ship.angle - .75 * pi, ship.angle + .75 * pi)
  322.                                         Next
  323.                                     End If ' big enough to split
  324.                                     b(i).live = 0 'kill bullet
  325.                                 End If ' hit rock
  326.                             End If 'rock is there
  327.                         Next ' rock
  328.                         If b(i).live Then fcirc b(i).x, b(i).y, 3, _RGB32(255, 255, 0) 'draws bullet
  329.                     Else
  330.                         b(i).live = 0 'out of bounds
  331.                     End If ' bullet is in bounds
  332.                 End If ' bullet live
  333.             Next ' bullet
  334.         End If ' if ship still live
  335.         _Display
  336.         If ship.live = 0 Then
  337.             lives = lives - 1
  338.             BolderOfDeathSpeed = BolderOfDeathSpeed + .2
  339.             If lives Mod 4 = 0 Then rocks = rocks + 1
  340.             If lives Mod 4 = 2 Then alienN = alienN + 1
  341.             s$ = "Lives:" + Str$(lives) + "  Hits:" + Str$(hits) + "  Bullets:" + Str$(bullets) + "  Shooting:" + Str$(Int(hits * 100 / bullets)) + "%"
  342.             _PrintString ((_Width - _PrintWidth(s$)) / 2, ymax / 2 - 80), s$
  343.             _Font fnt2
  344.             s$ = Str$(points) + hs$
  345.             _PrintString ((_Width - _PrintWidth(s$)) / 2, ymax / 2), s$
  346.             _Font fnt
  347.             s$ = "Press enter to enter next life."
  348.             _PrintString ((_Width - _PrintWidth(s$)) / 2, ymax / 2 + 120), s$
  349.             _Display
  350.             kh = 0
  351.             While kh <> 13
  352.                 kh = _KeyHit
  353.             Wend 'wait for enter key
  354.         Else
  355.             _Limit 60 ' if ship dies let's rest and regroup  before restart next life
  356.         End If
  357.     Wend
  358.     _Display
  359. If points > HS Then
  360.     Open "Asteroids High Score.txt" For Output As #1
  361.     Print #1, points
  362.     Close #1
  363. ship.x = -200: ship.y = -200 'get it out of the way
  364. i = 0
  365.     drawStars 0
  366.     i = i + 1
  367.     If i Mod 30 = 29 And rocks < nRocks Then rocks = rocks + 1: r(rocks).live = 1
  368.     For r = 1 To nRocks
  369.         If r(r).live Then DrawRock r
  370.     Next
  371.     s$ = "Lives:" + Str$(lives) + "  Hits:" + Str$(hits) + "  Bullets:" + Str$(bullets) + "  Shooting:" + Str$(Int(hits * 100 / bullets)) + "%"
  372.     _PrintString ((_Width - _PrintWidth(s$)) / 2, ymax / 2 - 80), s$
  373.     _Font fnt2
  374.     s$ = Str$(points)
  375.     If points > HS Then s$ = s$ + " a New Record!" Else s$ = Str$(points) + hs$
  376.     _PrintString ((_Width - _PrintWidth(s$)) / 2, ymax / 2), s$
  377.     _Font fnt
  378.     s$ = "Press q to Quit or a to play Again..."
  379.     _PrintString ((_Width - _PrintWidth(s$)) / 2, ymax / 2 + 120), s$
  380.     If _KeyDown(Asc("a")) Then GoTo restart
  381.     _Display
  382.     _Limit 60
  383.  
  384. Sub drawStars (moving)
  385.     Type starType
  386.         x As Single
  387.         y As Single
  388.         size As Single
  389.         c As Integer
  390.     End Type
  391.     Static beenHere, stars(200) As starType, cy As Long
  392.     Dim i As Long
  393.     If beenHere = 0 Then 'static part
  394.         For i = 0 To 100
  395.             stars(i).x = Rnd * xmax: stars(i).y = Rnd * ymax: stars(i).size = .3
  396.             stars(i).c = irnd&(80, 140)
  397.         Next
  398.         For i = 101 To 150
  399.             stars(i).x = Rnd * xmax: stars(i).y = Rnd * ymax: stars(i).size = .6
  400.             stars(i).c = irnd&(110, 170)
  401.         Next
  402.         For i = 151 To 195
  403.             stars(i).x = Rnd * xmax: stars(i).y = Rnd * ymax: stars(i).size = 1.2
  404.             stars(i).c = irnd&(140, 200)
  405.         Next
  406.         For i = 196 To 200
  407.             stars(i).x = Rnd * xmax: stars(i).y = Rnd * ymax: stars(i).size = 2.4
  408.             stars(i).c = irnd&(170, 235)
  409.         Next
  410.         cy = ymax / 2
  411.         beenHere = 1
  412.     End If
  413.     For i = 0 To cy
  414.         Line (0, i)-(xmax, i), _RGB32(0, 0, .1 * i + 4)
  415.         Line (0, ymax - i)-(xmax, ymax - i), _RGB(0, 0, .1 * i + 4)
  416.     Next
  417.     For i = 0 To 200
  418.         If moving Then
  419.             stars(i).x = stars(i).x + .2 * stars(i).size ^ stars(i).size
  420.             If stars(i).x > xmax Then stars(i).x = -1 * Rnd * 20
  421.         End If
  422.         fcirc stars(i).x, stars(i).y, stars(i).size, _RGB32(stars(i).c - 10, stars(i).c, stars(i).c + 10)
  423.     Next
  424.  
  425. Sub newAlien (i As Long)
  426.     Dim side As Long, heading
  427.     Randomize Timer * Rnd 'to avoid making twins
  428.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  429.     If Rnd < .6 Then
  430.         aliens(i).fireX = ship.x: aliens(i).fireY = ship.y
  431.     Else
  432.         aliens(i).fireX = irnd(10, xmax - 10): aliens(i).fireY = irnd(10, ymax - 10)
  433.     End If
  434.     aliens(i).attackFrame = irnd(50, 400) ' EDIT a tweak to survive a little long before getting murdered with low lives over and over...
  435.     Select Case side
  436.         Case 1
  437.             aliens(i).x = -10
  438.             aliens(i).y = rrnd(80, ymax - 80)
  439.         Case 2
  440.             aliens(i).x = xmax + 10
  441.             aliens(i).y = rrnd(80, ymax - 80)
  442.         Case 3
  443.             aliens(i).x = rrnd(80, xmax - 80)
  444.             aliens(i).y = -10
  445.         Case 4
  446.             aliens(i).x = rrnd(80, xmax - 80)
  447.             aliens(i).y = ymax + 10
  448.     End Select
  449.     heading = _Atan2(aliens(i).fireY - aliens(i).y, aliens(i).fireX - aliens(i).x)
  450.     aliens(i).dx = alienSpeed * Cos(heading)
  451.     aliens(i).dy = alienSpeed * Sin(heading)
  452.     aliens(i).live = 0
  453.     aliens(i).transform = 0
  454.     aliens(i).c = _RGB32(irnd(128, 255), irnd(0, 255), irnd(0, 255))
  455.  
  456. Function plasma~& (new As Long)
  457.     Static r, g, b, cnt, beenHere
  458.     If beenHere = 0 Or new Then
  459.         r = Rnd: g = Rnd: b = Rnd: beenHere = 1: cnt = 0
  460.     End If
  461.     cnt = cnt + .2
  462.     plasma~& = _RGB32(127 + 127 * Sin(r * cnt), 127 + 127 * Sin(g * cnt), 127 + 127 * Sin(b * cnt))
  463.  
  464. Sub drawAliens (i As Long) 'shipType
  465.     Dim light As Long, heading, r As Long, g As Long, b As Long
  466.     If aliens(i).live Then
  467.         Sound 6000 + i * 200, .07
  468.         If aliens(i).transform = 0 Then
  469.             r = _Red32(aliens(i).c): g = _Green32(aliens(i).c): b = _Blue32(aliens(i).c)
  470.             fellipse aliens(i).x, aliens(i).y, 6, 15, _RGB32(r, g - 120, b - 100)
  471.             fellipse aliens(i).x, aliens(i).y, 18, 11, _RGB32(r, g - 60, b - 50)
  472.             fellipse aliens(i).x, aliens(i).y, 30, 7, _RGB32(r, g, b)
  473.             For light = 0 To 5
  474.                 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)
  475.             Next
  476.             aliens(i).ls = aliens(i).ls + 1
  477.             If aliens(i).ls > 5 Then aliens(i).ls = 0
  478.         Else
  479.             drawBall aliens(i).x, aliens(i).y, 30, aliens(i).c
  480.         End If
  481.         'time to shoot?
  482.         aliens(i).x = aliens(i).x + aliens(i).dx
  483.         aliens(i).y = aliens(i).y + aliens(i).dy
  484.         If Sqr((aliens(i).fireX - aliens(i).x) ^ 2 + (aliens(i).fireY - aliens(i).y) ^ 2) < 5 Then 'transform into the bolder of death
  485.             aliens(i).transform = 1
  486.             heading = _Atan2(ship.y - aliens(i).y, ship.x - aliens(i).x)
  487.             aliens(i).dx = BolderOfDeathSpeed * Cos(heading)
  488.             aliens(i).dy = BolderOfDeathSpeed * Sin(heading)
  489.         End If
  490.         If aliens(i).x < -10 Or aliens(i).x > xmax + 10 Then
  491.             If aliens(i).y < -10 Or aliens(i).y > ymax + 10 Then '  out of bounds goodbye bolder of death!
  492.                 aliens(i).live = 0 'man we dodged a bullet here!!!!
  493.                 newAlien i 'reset the trap
  494.             End If
  495.         End If
  496.     Else
  497.         If aliens(i).attackFrame Then
  498.             aliens(i).attackFrame = aliens(i).attackFrame - 1
  499.             If aliens(i).attackFrame = 0 Then
  500.                 aliens(i).live = 1
  501.             End If
  502.         End If
  503.     End If
  504.  
  505. Function freeRock&
  506.     Dim i As Long
  507.     For i = rocks + 1 To nRocks ' look for inactive rock number
  508.         If r(i).live = 0 And r(i).explodeFrame = 0 Then freeRock& = i: Exit Function
  509.     Next
  510.  
  511. Sub explode (x As Long, y As Long, r As Long, frm As Long)
  512.     Dim maxParticles As Long, i As Long, rounds As Long, loopCount As Long
  513.     maxParticles = r * 4
  514.     For i = 1 To r
  515.         NewDot i, x, y, r
  516.     Next
  517.     rounds = r
  518.     For loopCount = 0 To frm
  519.         If _KeyDown(27) Then End
  520.         For i = 1 To rounds
  521.             dots(i).x = dots(i).x + dots(i).dx
  522.             dots(i).y = dots(i).y + dots(i).dy
  523.             fcirc dots(i).x, dots(i).y, dots(i).size, dots(i).kolor
  524.         Next
  525.         If rounds < maxParticles Then
  526.             For i = 1 To r
  527.                 NewDot (rounds + i), x, y, r
  528.             Next
  529.             rounds = rounds + r
  530.         End If
  531.     Next
  532.  
  533. Sub NewDot (i As Long, x As Long, y As Long, r As Long)
  534.     Dim angle, rd
  535.     angle = pi * 2 * Rnd
  536.     rd = Rnd * 30
  537.     dots(i).x = x + rd * Cos(angle)
  538.     dots(i).y = y + rd * Sin(angle)
  539.     dots(i).size = Rnd * r * .05
  540.     rd = Rnd 'STxAxTIC recommended for rounder spreads
  541.     dots(i).dx = rd * 10 * (10 - 2 * dots(i).size) * Cos(angle)
  542.     dots(i).dy = rd * 10 * (10 - 2 * dots(i).size) * Sin(angle)
  543.     rd = 20 + Rnd * 70
  544.     dots(i).kolor = _RGBA32(rd, rd, rd, 80)
  545.  
  546. Sub DrawShip 'simple red iso triangle pointed towards radianAngle
  547.     Dim As Long x1, y1, x2, y2, x3, y3, shipRadius
  548.     shipRadius = 50
  549.     x1 = ship.x + (shipRadius - 30) * Cos(ship.angle)
  550.     y1 = ship.y + (shipRadius - 30) * Sin(ship.angle)
  551.     x2 = ship.x + (shipRadius + 20) * Cos(ship.angle + _Pi(11 / 16))
  552.     y2 = ship.y + (shipRadius + 20) * Sin(ship.angle + _Pi(11 / 16))
  553.     x3 = ship.x + (shipRadius + 20) * Cos(ship.angle - _Pi(11 / 16))
  554.     y3 = ship.y + (shipRadius + 20) * Sin(ship.angle - _Pi(11 / 16))
  555.     ftri x1, y1, x2, y2, x3, y3, _RGB32(85, 45, 0)
  556.     x1 = ship.x + shipRadius * Cos(ship.angle)
  557.     y1 = ship.y + shipRadius * Sin(ship.angle)
  558.     x2 = ship.x + shipRadius * Cos(ship.angle + _Pi(7 / 8))
  559.     y2 = ship.y + shipRadius * Sin(ship.angle + _Pi(7 / 8))
  560.     x3 = ship.x + shipRadius * Cos(ship.angle - _Pi(7 / 8))
  561.     y3 = ship.y + shipRadius * Sin(ship.angle - _Pi(7 / 8))
  562.     ftri x1, y1, x2, y2, x3, y3, _RGB32(0, 0, 200)
  563.     x2 = ship.x + shipRadius * Cos(ship.angle + _Pi(15 / 16))
  564.     y2 = ship.y + shipRadius * Sin(ship.angle + _Pi(15 / 16))
  565.     x3 = ship.x + shipRadius * Cos(ship.angle - _Pi(15 / 16))
  566.     y3 = ship.y + shipRadius * Sin(ship.angle - _Pi(15 / 16))
  567.     ftri x1, y1, x2, y2, x3, y3, _RGB32(255, 255, 255)
  568.  
  569. Sub DrawRock (iRock)
  570.     Randomize Using r(iRock).seed 'this prevents having to save a particular sequence of random number
  571.     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
  572.     Dim x2 As Long, y2 As Long
  573.     dx = r(iRock).speed * Cos(r(iRock).heading)
  574.     dy = r(iRock).speed * Sin(r(iRock).heading) 'update location
  575.     r(iRock).ra = r(iRock).ra + r(iRock).spin
  576.     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
  577.         If iRock <= rocks Then newRock iRock Else r(iRock).live = 0
  578.         Exit Sub ' reassigned get out of here
  579.     Else
  580.         r(iRock).x = r(iRock).x + dx
  581.         r(iRock).y = r(iRock).y + dy
  582.     End If
  583.     For j = 10 To 3 Step -1 '                  rock drawing (see demo program where developed code)
  584.         rRad = .1 * j * r(iRock).r
  585.         leg = rRad * (Rnd * .7 + .3)
  586.         x0 = r(iRock).x + leg * Cos(r(iRock).ra)
  587.         y0 = r(iRock).y + leg * Sin(r(iRock).ra)
  588.         rc = r(iRock).c + 30 * Rnd - 15
  589.         c~& = _RGB32(rc + 5, rc - 10, rc + 5)
  590.         x1 = x0
  591.         y1 = y0
  592.         xoff = Rnd * 20 - 10 + r(iRock).x
  593.         yoff = Rnd * 20 - 10 + r(iRock).y
  594.         For i = 1 To 12
  595.             leg = rRad * (Rnd * .35 + .65)
  596.             If i = 12 Then
  597.                 x2 = x0: y2 = y0
  598.             Else
  599.                 x2 = xoff + leg * Cos(i * polyAngle + r(iRock).ra)
  600.                 y2 = yoff + leg * Sin(i * polyAngle + r(iRock).ra)
  601.             End If
  602.             ftri r(iRock).x, r(iRock).y, x1, y1, x2, y2, c~&
  603.             x1 = x2: y1 = y2
  604.         Next
  605.     Next
  606.  
  607. Sub newRock (iRock)
  608.     Dim side As Long
  609.     Randomize Timer * Rnd 'to avoid making twins
  610.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  611.     Select Case side
  612.         Case 1
  613.             r(iRock).x = -100
  614.             r(iRock).y = rrnd(80, ymax - 80)
  615.             If Rnd < .25 Then r(iRock).heading = _Atan2(ship.y - r(iRock).y, ship.x - r(iRock).x) Else r(iRock).heading = 3 * pi / 2 + Rnd * pi
  616.         Case 2
  617.             r(iRock).x = xmax + 100
  618.             r(iRock).y = rrnd(80, ymax - 80)
  619.             If Rnd < .25 Then r(iRock).heading = _Atan2(ship.y - r(iRock).y, ship.x - r(iRock).x) Else r(iRock).heading = pi / 2 + Rnd * pi
  620.         Case 3
  621.             r(iRock).x = rrnd(80, xmax - 80)
  622.             r(iRock).y = -100
  623.             If Rnd < .25 Then r(iRock).heading = _Atan2(ship.y - r(iRock).y, ship.x - r(iRock).x) Else r(iRock).heading = Rnd * pi
  624.         Case 4
  625.             r(iRock).x = rrnd(80, xmax - 80)
  626.             r(iRock).y = ymax + 100
  627.             If Rnd < .25 Then r(iRock).heading = _Atan2(ship.y - r(iRock).y, ship.x - r(iRock).x) Else r(iRock).heading = pi + Rnd * pi
  628.     End Select
  629.     r(iRock).speed = rrnd(minRockSpeed, maxRockSpeed) 'speed, rotation angle, radius, gray coloring, spin, seed, hit for explosion
  630.     r(iRock).ra = Rnd * 2 * pi
  631.     r(iRock).r = irnd&(minRockSize * 3, maxRockSize) 'every parent rock can be split up into at least 2 - 10 size rocks
  632.     r(iRock).c = irnd&(60, 110) ' Ken request increase in rock color
  633.     r(iRock).spin = rrnd(-pi / 20, pi / 20)
  634.     r(iRock).seed = Int(Rnd * 64000) - 32000
  635.     r(iRock).explodeFrame = 0
  636.     r(iRock).live = 1
  637.  
  638. Function irnd& (n1, n2) 'return an integer between 2 numbers
  639.     Dim l%, h%
  640.     If n1 > n2 Then l% = n2: h% = n1 Else l% = n1: h% = n2
  641.     irnd& = Int(Rnd * (h% - l% + 1)) + l%
  642.  
  643. Function rrnd (n1, n2) ' return number (expecting reals =_single, double, _float depending on default / define setup)
  644.     rrnd = (n2 - n1) * Rnd + n1
  645.  
  646. Sub drawBall (x, y, r, c As _Unsigned Long)
  647.     Dim red As Long, grn As Long, blu As Long, rr As Long, f
  648.     red = _Red32(c): grn = _Green32(c): blu = _Blue32(c)
  649.     For rr = r To 0 Step -1
  650.         f = 1 - rr / r
  651.         fcirc x, y, rr, _RGB32(red * f, grn * f, blu * f)
  652.     Next
  653.  
  654. Sub fellipse (CX As Long, CY As Long, xr As Long, yr As Long, C As _Unsigned Long)
  655.     If xr = 0 Or yr = 0 Then Exit Sub
  656.     Dim x As Long, y As Long
  657.     w2 = xr * xr: h2 = yr * yr: h2w2 = h2 * w2
  658.     Line (CX - xr, CY)-(CX + xr, CY), C, BF
  659.     Do While y < yr
  660.         y = y + 1
  661.         x = Sqr((h2w2 - y * y * w2) \ h2)
  662.         Line (CX - x, CY + y)-(CX + x, CY + y), C, BF
  663.         Line (CX - x, CY - y)-(CX + x, CY - y), C, BF
  664.     Loop
  665.  
  666. Sub ftri (x1, y1, x2, y2, x3, y3, K As _Unsigned Long)
  667.     Dim D As Long
  668.     Static a&
  669.     D = _Dest
  670.     If a& = 0 Then a& = _NewImage(1, 1, 32)
  671.     _Dest a&
  672.     _DontBlend a& '  '<<<< new 2019-12-16 fix
  673.     PSet (0, 0), K
  674.     _Blend a& '<<<< new 2019-12-16 fix
  675.     _Dest D
  676.     _MapTriangle _Seamless(0, 0)-(0, 0)-(0, 0), a& To(x1, y1)-(x2, y2)-(x3, y3)
  677.  
  678. Sub fcirc (x As Long, y As Long, R As Long, C As _Unsigned Long) 'vince version
  679.     Dim x0 As Long, y0 As Long, e As Long
  680.     x0 = R: y0 = 0: e = 0
  681.     Do While y0 < x0
  682.         If e <= 0 Then
  683.             y0 = y0 + 1
  684.             Line (x - x0, y + y0)-(x + x0, y + y0), C, BF
  685.             Line (x - x0, y - y0)-(x + x0, y - y0), C, BF
  686.             e = e + 2 * y0
  687.         Else
  688.             Line (x - y0, y - x0)-(x + y0, y - x0), C, BF
  689.             Line (x - y0, y + x0)-(x + y0, y + x0), C, BF
  690.             x0 = x0 - 1: e = e - 2 * x0
  691.         End If
  692.     Loop
  693.     Line (x - R, y)-(x + R, y), C, BF
  694.  
  695. 'convert output of _ATAN2 to positive Radian Angle
  696. Function PositiveRA# (ra As Double) ' having trouble comparing angles returned from _ATAN2
  697.     ReDim raa As Double
  698.     raa = ra ' dont change ra here
  699.     While raa < 0
  700.         raa = raa + 6.283185307179586
  701.     Wend
  702.     While raa > _Pi(2)
  703.         raa = raa - 6.283185307179586
  704.     Wend
  705.     PositiveRA# = raa
  706.  
  707. 'convert Positive Radian Angle back to Radian Angle between -pi and pi
  708. Function PlusMinusPiRA# (ra As Double)
  709.     ReDim raa As Double
  710.     raa = ra ' dont change ra here
  711.     While raa < -3.141592653589793
  712.         raa = raa + 6.283185307179586
  713.     Wend
  714.     While raa > 3.141592653589793
  715.         raa = raa - 6.283185307179586
  716.     Wend
  717.     PlusMinusPiRA# = raa
  718.  
  719.  

The higher levels really get crazy!

Attached is font file I used.

b+QB64 Asteroids - MAS.PNG
* b+QB64 Asteroids - MAS.PNG (Filesize: 70.72 KB, Dimensions: 1055x606, Views: 59)
* ARLRDBD.TTF (Filesize: 44.2 KB, Downloads: 35)
« Last Edit: April 03, 2021, 10:39:39 pm by bplus »