QB64.org Forum

Active Forums => Programs => Topic started by: bplus on October 27, 2020, 04:19:05 pm

Title: b+ Asteroids makeover
Post by: bplus on October 27, 2020, 04:19:05 pm
New (old stars.png) background, font, coloring and specially shooter action. Use mouse to point shooter / ship and use spacebar to shoot and about 100 less LOC, yeah I did double park :)

So much better than arrow keys! Asteroids are all uniquely drawn and spun.

zip has bas source, font and background image.



Title: Re: b+ Asteroids makeover
Post by: SierraKen on October 27, 2020, 09:42:35 pm
That is really good B+! You are a good artist. Do you have plans to add break-ups on the asteroids and sound? I'm not sure how I would do the math myself for break-ups but you can try it if you want. The mouse does make it work great. An easy way I guess to do the math would just not use math and make random trajectories on the smaller asteroids.
Title: Re: b+ Asteroids makeover
Post by: bplus on October 27, 2020, 11:14:20 pm
Thanks Ken, they're suppose to break up? and pose further threat I suppose. :)

That does sound good... I know I could do better explosions... hmm...
Title: Re: b+ Asteroids makeover
Post by: SierraKen on October 28, 2020, 12:54:36 am
Yes, here is the original arcade version. But there's been countless versions over the years and yours looks 100x better than the original of course.
But notice how they break up and also how your ship can fly around. When he goes off the screen, he appears on the opposite side. Plus there's the UFO ships if you really want to get involved.

https://www.youtube.com/watch?v=WYSupJ5r2zo (https://www.youtube.com/watch?v=WYSupJ5r2zo)
Title: Re: b+ Asteroids makeover
Post by: johnno56 on October 28, 2020, 06:41:20 am
Who doesn't like a good Asteroids game? Another cool version... Nicely done!
Title: Re: b+ Asteroids makeover
Post by: bplus on October 28, 2020, 10:56:57 am
Little experiment about increasing rock count while in a rock count loop
Code: QB64: [Select]
  1. top = 10
  2. FOR i = 1 TO top
  3.     IF i = 2 THEN top = top + 1
  4.     PRINT i
  5. ' good it stops at first top value
  6. FOR i = 1 TO top
  7.     IF i = 2 THEN top = top + 1
  8.     PRINT i
  9. 'good it stops at 2nd top value
  10.  
  11.  
Title: Re: b+ Asteroids makeover
Post by: SierraKen on October 28, 2020, 01:23:06 pm
:) If I remember right, the asteroids can break up twice before totally disintagrating.
Title: Re: b+ Asteroids makeover
Post by: Dav on October 28, 2020, 01:29:09 pm
Cool!  I've always like Asteroids games.  Nice tight code, @bplus!  I added a few SFX here for fun.  Thanks for sharing your work.

- Dav

Title: Re: b+ Asteroids makeover
Post by: bplus on October 28, 2020, 01:33:07 pm
Yeah I am in process of converting back to UDT's to apply explosions and splittings.

I do need sound effects (no .ogg), wait can you hear explosions in space?

;-))
Title: Re: b+ Asteroids makeover
Post by: bplus on October 29, 2020, 11:57:03 am
Update: switched over to UDT's, freed ship to move around, new shooter action, added explosions = cool!, and splitting larger rocks into baby ones. Baby rock management a bear but it was getting late.

Again new shooter action, I liked what I saw in MonoSpac only I am using Left / Right Mouse button to flip the gun left and right, now if I can only remember my left from my right ;-)) on man!
But accuracy has jumped up from 10-20% to 60-80% depending how trigger happy you are.

You need to be very careful now shooting at big rocks too close to ship.

Funny I was shooting bullets and hitting ghost rocks!   WTH?  ah they might not be showing but they were still there in the arrays ;-))
Title: Re: b+ Asteroids makeover
Post by: SierraKen on October 29, 2020, 01:00:47 pm
It sounds great, can't wait to see it. :)
Title: Re: b+ Asteroids makeover
Post by: bplus on October 29, 2020, 04:29:49 pm
It sounds great, can't wait to see it. :)

Neither can I :-)) actually baby rock management a piece of cake, now working on increasing level difficulty.

Here is snapshot of WIP:
Code: QB64: [Select]
  1. _TITLE "b+ Asteroids m2" 'started 2018-07-13"
  2. ' 2020-10-27 remove the alternate subs and get down below 200 LOC almost there now! new shooter action font and background
  3. ' 2020-10-28 another makeover explosions and split asteroids
  4. ' 2020-10-29 fix baby rock management, break between lives
  5.  
  6. CONST xmax = 1200, ymax = 700, pi = _PI, polyAngle = _PI / 6, nRocks = 100, nBullets = 1000, bSpeed = 30
  7.  
  8. TYPE particle
  9.     x AS SINGLE
  10.     y AS SINGLE
  11.     dx AS SINGLE
  12.     dy AS SINGLE
  13.     size AS SINGLE
  14.     kolor AS LONG
  15.  
  16. TYPE bullet
  17.     x AS LONG
  18.     y AS LONG
  19.     dx AS SINGLE
  20.     dy AS SINGLE
  21.     live AS LONG
  22.  
  23. TYPE shipType
  24.     x AS LONG
  25.     y AS LONG
  26.     live AS LONG
  27.     a AS SINGLE
  28.  
  29. TYPE rock
  30.     x AS LONG
  31.     y AS LONG
  32.     r AS LONG 'radius
  33.     ra AS SINGLE 'rotation angle  a = a + spin
  34.     heading AS SINGLE 'heading from which dx, dy are calc with speed
  35.     speed AS SINGLE 'speed
  36.     spin AS SINGLE
  37.     seed AS LONG
  38.     c AS INTEGER 'color   rgb(grey)
  39.     hit AS LONG 'TF or count before or after hit  not sure I need this from explosions
  40.     live AS LONG 'need this to track rocks still active like bullets
  41.  
  42. DIM SHARED dots(2000) AS particle
  43. DIM SHARED b(nBullets) AS bullet
  44. DIM SHARED ship AS shipType
  45. DIM SHARED r(nRocks) AS rock
  46. DIM SHARED lives&, rocks& '   rocks is the minimum number of parent rocks to have on screen  automatic replace when hit or out of bounds, always live
  47.  
  48. SCREEN _NEWIMAGE(xmax, ymax, 32)
  49. _SCREENMOVE 100, 20
  50.  
  51. stars& = _LOADIMAGE("stars.png", 32)
  52. fnt& = _LOADFONT("ARLRDBD.ttf", 12, "MONOSPACE")
  53. _FONT fnt&
  54. COLOR &HFF00FFFF, &H00000000
  55. rocks& = 6 ' always active rocks
  56. lives& = 100
  57.  
  58. WHILE lives& AND _KEYDOWN(27) = 0 ' init start restart
  59.     FOR i = 1 TO nRocks 'reset rocks mainly clear baby rocks
  60.         newRock (i)
  61.         IF i > rocks& THEN r(i).live = 0
  62.     NEXT
  63.     ship.x = xmax / 2 'avoids explosions top left corner at start
  64.     ship.y = ymax / 2
  65.     ship.live = 1
  66.  
  67.     WHILE ship.live AND _KEYDOWN(27) = 0
  68.  
  69.         'draw everything then process bullets
  70.         _PUTIMAGE , stars&
  71.         S$ = "Lives:" + STR$(lives&) + "  Hits:" + STR$(Hits&) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(Hits& * 100 / bullets)) + "%"
  72.         _PRINTSTRING ((_WIDTH - _PRINTWIDTH(S$)) / 2, ymax / 2), S$
  73.         FOR i = 1 TO nRocks
  74.             IF r(i).live THEN drawRock (i) ' while drawing rocks the ship could be blown up
  75.         NEXT
  76.         IF ship.live THEN
  77.             drawship
  78.  
  79.             WHILE _MOUSEINPUT: WEND 'update ship
  80.             ship.x = _MOUSEX: ship.y = _MOUSEY
  81.             IF lastx <> ship.x OR lasty <> ship.y THEN
  82.                 lastx = ship.x: lasty = ship.y
  83.             ELSE
  84.                 IF _MOUSEBUTTON(1) THEN ship.a = pi 'this is new left and right guns
  85.                 IF _MOUSEBUTTON(2) THEN ship.a = 0
  86.                 IF _KEYDOWN(ASC("w")) THEN ship.a = 1.5 * pi ' well it works but ??
  87.                 IF _KEYDOWN(ASC("z")) THEN ship.a = .5 * pi
  88.             END IF
  89.  
  90.             fire = 0
  91.             IF _KEYDOWN(32) THEN 'fire bullets
  92.                 t = TIMER(.01)
  93.                 IF lastt = 0 OR t - lastt > .2 THEN fire = 1: lastt = t: bullets = bullets + 1
  94.             END IF
  95.  
  96.             FOR i = 0 TO nBullets 'handle bullets
  97.                 IF b(i).live = 0 AND fire = 1 THEN 'have inactive bullet to use
  98.                     b(i).x = ship.x + bSpeed * COS(ship.a)
  99.                     b(i).y = ship.y + bSpeed * SIN(ship.a)
  100.                     b(i).dx = bSpeed * COS(ship.a)
  101.                     b(i).dy = bSpeed * SIN(ship.a)
  102.                     b(i).live = -1
  103.                     fire = 0
  104.                 END IF
  105.  
  106.                 IF b(i).live THEN 'new location
  107.                     b(i).x = b(i).x + b(i).dx
  108.                     b(i).y = b(i).y + b(i).dy
  109.                     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
  110.                         FOR r = 1 TO nRocks 'check for collision with rock
  111.                             IF r(r).live THEN
  112.                                 IF SQR((r(r).x - b(i).x) ^ 2 + (r(r).y - b(i).y) ^ 2) < r(r).r THEN 'its a hit!
  113.                                     explode r(r).x, r(r).y, r(r).r, r(r).r - r(r).hit
  114.                                     Hits& = Hits& + 1
  115.  
  116.  
  117.                                     '                     for reference
  118.                                     'x AS LONG
  119.                                     'y AS LONG
  120.                                     'r AS LONG 'radius
  121.                                     'ra AS SINGLE 'rotation angle  a = a + spin
  122.                                     'heading AS SINGLE 'heading from which dx, dy are calc with speed
  123.                                     'speed AS SINGLE 'speed
  124.                                     'spin AS SINGLE
  125.                                     'seed AS LONG
  126.                                     'c AS INTEGER 'color   rgb(grey)
  127.                                     'hit AS LONG 'TF or count before or after hit  not sure I need this from explosions
  128.                                     'live AS INTEGER 'need this to track rocks still active like bullets
  129.  
  130.                                     IF r(r).r > 30 THEN '       split rock
  131.                                         '                        new rock
  132.                                         newRockN = freeRock& '                      get inactive rock number
  133.                                         newRock newRockN '                         new identity and activate
  134.  
  135.                                         '_PRINTSTRING (xmax / 2, ymax / 4), "NewRock " + STR$(newRockN)
  136.                                         '_DISPLAY
  137.  
  138.                                         r(newRockN).r = (r(r).r - 10) / 2 '        split in half minus 20% mass
  139.                                         r(newRockN).x = r(r).x + irnd&(-10, 10) ' thrown from parent
  140.                                         r(newRockN).y = r(r).y + irnd&(-10, 10)
  141.                                         r(newRockN).c = r(r).c '                   same color as parent
  142.                                         r(newRockN).heading = rrnd(ship.a, ship.a + pi / 2)
  143.                                         'r(newRockN).live = 1
  144.  
  145.                                         ' remainder of rock carries on smaller and changed
  146.                                         r(r).r = (r(r).r - 10) / 2 '         split in half minus 20% mass
  147.                                         r(r).x = r(r).x + irnd&(-5, 5) '    thrown  a bit
  148.                                         r(r).y = r(r).y + irnd&(-5, 5)
  149.                                         r(r).heading = rrnd(ship.a, ship.a - pi / 2)
  150.                                         r(r).ra = RND * 2 * pi '             twisted
  151.                                         r(r).speed = rrnd(3, 7) '            different
  152.                                         r(r).spin = rrnd(-pi / 10, pi / 10) 'different
  153.                                         'r(r).live = 1
  154.  
  155.                                     ELSE ' not big enough to split
  156.                                         IF r <= rocks& THEN newRock r ELSE r(r).live = 0
  157.                                     END IF ' big enough to split
  158.                                     b(i).live = 0 'kill bullet
  159.                                 END IF ' hit rock
  160.                             END IF 'rock is there
  161.                         NEXT ' rock
  162.                         IF b(i).live THEN fcirc b(i).x, b(i).y, 3, _RGB32(255, 255, 0) 'draws bullet
  163.                     ELSE
  164.                         b(i).live = 0 'out of bounds
  165.                     END IF ' bullet is in bounds
  166.                 END IF ' bullet live
  167.             NEXT ' bullet
  168.         END IF ' if ship still live
  169.         _DISPLAY
  170.         IF ship.live = 0 THEN SLEEP ELSE _LIMIT 30 ' if ship dies let's rest and regroup  before restart next life
  171.     WEND
  172.     lives& = lives& - 1
  173.  
  174. FUNCTION freeRock&
  175.     FOR i& = rocks& + 1 TO nRocks ' look for inactive rock number
  176.         IF r(i&).live = 0 THEN freeRock& = i&: EXIT FUNCTION
  177.     NEXT
  178.     BEEP 'when we can't find a free rock
  179.  
  180. SUB explode (x, y, r, frm)
  181.     maxParticles = r * 10
  182.     FOR i = 1 TO r
  183.         NewDot i, x, y, r
  184.     NEXT
  185.     rounds = r
  186.     FOR loopCount = 0 TO frm
  187.         IF _KEYDOWN(27) THEN END
  188.         FOR i = 1 TO rounds
  189.             dots(i).x = dots(i).x + dots(i).dx
  190.             dots(i).y = dots(i).y + dots(i).dy
  191.             dots(i).dx = dots(i).dx * .9
  192.             dots(i).dy = dots(i).dy * .9
  193.             fcirc dots(i).x, dots(i).y, dots(i).size / 2, dots(i).kolor
  194.         NEXT
  195.         IF rounds < maxParticles THEN
  196.             FOR i = 1 TO r
  197.                 NewDot (rounds + i), x, y, r
  198.             NEXT
  199.             rounds = rounds + r
  200.         END IF
  201.         _LIMIT 300
  202.         _DISPLAY
  203.     NEXT
  204.  
  205. SUB NewDot (i, x, y, r)
  206.     angle = pi * 2 * RND
  207.     rd = RND * 30
  208.     dots(i).x = x + rd * COS(angle)
  209.     dots(i).y = y + rd * SIN(angle)
  210.     dots(i).size = RND * r * .1
  211.     rd = RND 'STxAxTIC recommended for rounder spreads
  212.     dots(i).dx = rd * 7 * (7 - dots(i).size) * COS(angle)
  213.     dots(i).dy = rd * 7 * (7 - dots(i).size) * SIN(angle)
  214.     rd = 20 + RND * 70
  215.     dots(i).kolor = _RGBA32(rd, rd, rd, 40)
  216.  
  217. SUB drawship 'simple red iso triangle pointed towards radianAngle
  218.     'calculate 3 tail points of triangle ship
  219.     x1 = ship.x + 40 * COS(ship.a - pi) '   middle
  220.     y1 = ship.y + 40 * SIN(ship.a - pi) '
  221.     x2 = ship.x + 60 * COS(ship.a + .9 * pi) ' wing
  222.     y2 = ship.y + 60 * SIN(ship.a + .9 * pi)
  223.     x3 = ship.x + 60 * COS(ship.a - .9 * pi) ' other wing
  224.     y3 = ship.y + 60 * SIN(ship.a - .9 * pi)
  225.     ftri ship.x, ship.y, x1, y1, x2, y2, _RGB32(80, 120, 80, 80)
  226.     ftri ship.x, ship.y, x1, y1, x3, y3, _RGB32(60, 100, 60, 80)
  227.     LINE (ship.x, ship.y)-(x1, y1), _RGB32(255, 255, 128)
  228.     LINE (ship.x, ship.y)-(x2, y2), _RGB32(180, 180, 120)
  229.     LINE (ship.x, ship.y)-(x3, y3), _RGB32(180, 180, 120)
  230.  
  231. SUB drawRock (iRock)
  232.     '                     for reference
  233.     'x AS LONG
  234.     'y AS LONG
  235.     'r AS LONG 'radius
  236.     'ra AS SINGLE 'rotation angle  a = a + spin
  237.     'heading AS SINGLE 'heading from which dx, dy are calc with speed
  238.     'speed AS SINGLE 'speed
  239.     'spin AS SINGLE
  240.     'seed AS LONG
  241.     'c AS INTEGER 'color   rgb(grey)
  242.     'hit AS LONG 'TF or count before or after hit  not sure I need this from explosions
  243.     'live AS INTEGER 'need this to track rocks still active like bullets
  244.  
  245.     RANDOMIZE USING r(iRock).seed 'this prevents having to save a particular sequence of random numbers
  246.     dx = r(iRock).speed * COS(r(iRock).heading)
  247.     dy = r(iRock).speed * SIN(r(iRock).heading) 'update location
  248.     r(iRock).ra = r(iRock).ra + r(iRock).spin
  249.     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 + yx - r(iRock).r > ymax THEN
  250.         IF iRock <= rocks& THEN newRock iRock ELSE r(iRock).live = 0
  251.         EXIT SUB ' ressigned get out of here
  252.     ELSE
  253.         r(iRock).x = r(iRock).x + dx
  254.         r(iRock).y = r(iRock).y + dy
  255.     END IF
  256.     IF ((r(iRock).x - ship.x) ^ 2 + (r(iRock).y - ship.y) ^ 2) ^ .5 < r(iRock).r + 30 THEN 'rock collides with ship?
  257.         FOR rad = 1 TO 200
  258.             fcirc ship.x, ship.y, rad, _RGB32(255 - rad, 255 - 2 * rad, 0)
  259.             _DISPLAY
  260.             _LIMIT 300
  261.         NEXT
  262.         lives& = lives& - 1
  263.         IF iRock <= rocks& THEN newRock iRock ELSE r(iRock).live = 0
  264.         EXIT SUB
  265.     END IF
  266.     FOR j = 10 TO 3 STEP -1 '                  rock drawing (see demo program where developed code)
  267.         rRad = .1 * j * r(iRock).r
  268.         leg = rRad * (RND * .7 + .3)
  269.         x0 = r(iRock).x + leg * COS(r(iRock).ra)
  270.         y0 = r(iRock).y + leg * SIN(r(iRock).ra)
  271.         rc = r(iRock).c + 30 * RND - 15
  272.         c& = _RGB32(rc + 5, rc - 10, rc + 5)
  273.         x1 = x0
  274.         y1 = y0
  275.         xoff = RND * 20 - 10 + r(iRock).x
  276.         yoff = RND * 20 - 10 + r(iRock).y
  277.         FOR i = 1 TO 12
  278.             leg = rRad * (RND * .35 + .65)
  279.             IF i = 12 THEN
  280.                 x2 = x0: y2 = y0
  281.             ELSE
  282.                 x2 = xoff + leg * COS(i * polyAngle + r(iRock).ra)
  283.                 y2 = yoff + leg * SIN(i * polyAngle + r(iRock).ra)
  284.             END IF
  285.             ftri r(iRock).x, r(iRock).y, x1, y1, x2, y2, c&
  286.             x1 = x2: y1 = y2
  287.         NEXT
  288.     NEXT
  289.  
  290. SUB newRock (iRock)
  291.     '                     for reference
  292.     'x AS LONG
  293.     'y AS LONG
  294.     'r AS LONG 'radius
  295.     'ra AS SINGLE 'rotation angle  a = a + spin
  296.     'heading AS SINGLE 'heading from which dx, dy are calc with speed
  297.     'speed AS SINGLE 'speed
  298.     'spin AS SINGLE
  299.     'seed AS LONG
  300.     'c AS INTEGER 'color   rgb(grey)
  301.     'hit AS LONG 'TF or count before or after hit  not sure I need this from explosions
  302.     'live AS INTEGER 'need this to track rocks still active like bullets
  303.  
  304.     RANDOMIZE TIMER * RND 'to avoid making twins
  305.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  306.     SELECT CASE side
  307.         CASE 1
  308.             r(iRock).x = -10
  309.             r(iRock).y = rrnd(20, ymax - 20)
  310.             r(iRock).heading = 3 * pi / 2 + RND * pi
  311.         CASE 2
  312.             r(iRock).x = xmax + 10
  313.             r(iRock).y = rrnd(20, ymax - 20)
  314.             r(iRock).heading = pi / 2 + RND * pi
  315.         CASE 3
  316.             r(iRock).x = rrnd(20, xmax - 20)
  317.             r(iRock).y = -10
  318.             r(iRock).heading = RND * pi
  319.         CASE 4
  320.             r(iRock).x = rrnd(20, xmax - 20)
  321.             r(iRock).y = ymax + 10
  322.             r(iRock).heading = pi + RND * pi
  323.     END SELECT
  324.     r(iRock).speed = rrnd(3, 7) 'speed, rotation angle, radius, gray coloring, spin, seed, hit for explosion
  325.     r(iRock).ra = RND * 2 * pi
  326.     r(iRock).r = irnd&(30, 100)
  327.     r(iRock).c = irnd&(10, 60)
  328.     r(iRock).spin = rrnd(-pi / 10, pi / 10)
  329.     r(iRock).seed = INT(RND * 64000) - 32000
  330.     r(iRock).hit = 0
  331.     r(iRock).live = 1
  332.  
  333. FUNCTION irnd& (n1, n2) 'return an integer between 2 numbers
  334.     DIM l%, h%
  335.     IF n1 > n2 THEN l% = n2: h% = n1 ELSE l% = n1: h% = n2
  336.     irnd& = INT(RND * (h% - l% + 1)) + l%
  337.  
  338. FUNCTION rrnd (n1, n2) 'return real number (_single, double, _float depending on default / define setup)
  339.     rrnd = (n2 - n1) * RND + n1
  340.  
  341. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  342.     DIM D AS LONG
  343.     STATIC a&
  344.     D = _DEST
  345.     IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32)
  346.     _DEST a&
  347.     _DONTBLEND a& '  '<<<< new 2019-12-16 fix
  348.     PSET (0, 0), K
  349.     _BLEND a& '<<<< new 2019-12-16 fix
  350.     _DEST D
  351.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  352.  
  353. SUB fcirc (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG) 'vince version
  354.     x0 = R: y0 = 0: e = 0
  355.     DO WHILE y0 < x0
  356.         IF e <= 0 THEN
  357.             y0 = y0 + 1
  358.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  359.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  360.             e = e + 2 * y0
  361.         ELSE
  362.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  363.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  364.             x0 = x0 - 1: e = e - 2 * x0
  365.         END IF
  366.     LOOP
  367.     LINE (x - R, y)-(x + R, y), C, BF
  368.  

Same assets as in zip
Title: Re: b+ Asteroids makeover
Post by: bplus on October 29, 2020, 09:23:04 pm
Dah! This is why I think I don't know my left from my right:
Code: QB64: [Select]
  1.             WHILE _MOUSEINPUT: WEND 'update ship
  2.             ship.x = _MOUSEX: ship.y = _MOUSEY
  3.             IF lastx <> ship.x OR lasty <> ship.y THEN
  4.                 lastx = ship.x: lasty = ship.y
  5.             ELSE
  6.                 IF _MOUSEBUTTON(1) THEN ship.a = pi 'this is new left and right guns
  7.                 IF _MOUSEBUTTON(2) THEN ship.a = 0
  8.                 IF _KEYDOWN(ASC("w")) THEN ship.a = 1.5 * pi ' well it works but ??
  9.                 IF _KEYDOWN(ASC("z")) THEN ship.a = .5 * pi
  10.             END IF
  11.  
Remnants of the previous shooter code, get rid of IF stuff!  and lastx, lasty

Code: QB64: [Select]
  1.             WHILE _MOUSEINPUT: WEND 'update ship
  2.             ship.x = _MOUSEX: ship.y = _MOUSEY
  3.             IF _MOUSEBUTTON(1) THEN ship.a = pi 'this is new left and right guns
  4.             IF _MOUSEBUTTON(2) THEN ship.a = 0
  5.             IF _KEYDOWN(ASC("w")) THEN ship.a = 1.5 * pi ' well it works but ??
  6.             IF _KEYDOWN(ASC("z")) THEN ship.a = .5 * pi
  7.  

The option to point the gun up or down is there with w, z key press but I don't like taking my left hand off the space bar and taking my eyes off the screen to look for keys.

And are you noticing the slight delay while a rock hit is exploding, I think I had explode worked out to go several frames, that was what frm was, I think...  hmm... how to work that?
Title: Re: b+ Asteroids makeover
Post by: bplus on October 30, 2020, 02:03:38 am
An update with explosions stretched out over several frames so the action isn't paused, sped up.

Code: QB64: [Select]
  1. _TITLE "b+ Asteroids m2" 'started 2018-07-13"
  2. ' 2020-10-27 remove the alternate subs and get down below 200 LOC almost there now! new shooter action font and background
  3. ' 2020-10-28 another makeover explosions and split asteroids
  4. ' 2020-10-29 fix baby rock management, break between lives
  5. ' 2020-10-29 fix left/right gun, fix explosions over many frames to eliminate pause in action, speed up 60 fps
  6.  
  7. '================================================================================================================
  8.  
  9. '    NOTE: !!!!!!!!!!!!!!!   When there is a pause in action, just hit any key to reset next life.
  10.  
  11. '================================================================================================================
  12.  
  13. CONST xmax = 1200, ymax = 700, pi = _PI, polyAngle = _PI / 6, nRocks = 100, nBullets = 2000, bSpeed = 15
  14.  
  15. TYPE particle
  16.     x AS LONG
  17.     y AS LONG
  18.     dx AS SINGLE
  19.     dy AS SINGLE
  20.     size AS SINGLE
  21.     kolor AS _UNSIGNED LONG
  22.  
  23. TYPE bullet
  24.     x AS LONG
  25.     y AS LONG
  26.     dx AS SINGLE
  27.     dy AS SINGLE
  28.     live AS LONG
  29.  
  30. TYPE shipType
  31.     x AS LONG
  32.     y AS LONG
  33.     live AS LONG
  34.     a AS SINGLE '   rotated position usu gun left or right (mouse button), maybe up press w or down press z
  35.  
  36. TYPE rock
  37.     x AS LONG
  38.     y AS LONG
  39.     r AS LONG '            radius
  40.     ra AS SINGLE '         rotation position   a = a + spin
  41.     heading AS SINGLE '    heading from which dx, dy are calc with speed
  42.     speed AS SINGLE '      speed
  43.     spin AS SINGLE '       rotation direction and amount
  44.     seed AS LONG '         for drawing rocks with RND USING
  45.     c AS LONG '            color   rgb(c, c, c)
  46.     live AS LONG '         need this to track rocks still active like bullets
  47.     explodeFrame AS LONG ' after a rock is hit by bullet, it explodes and in more than one frame
  48.  
  49. DIM SHARED dots(2000) AS particle
  50. DIM SHARED b(nBullets) AS bullet
  51. DIM SHARED ship AS shipType
  52. DIM SHARED r(nRocks) AS rock
  53. DIM SHARED lives&, rocks& '   rocks is the minimum number of parent rocks to have on screen  automatic replace when hit or out of bounds, always live
  54. DIM i AS LONG, bullets AS LONG, fire AS LONG, stars&, fnt&, s$, hits&, t, lastt, r AS LONG, newRockN AS LONG
  55.  
  56. SCREEN _NEWIMAGE(xmax, ymax, 32)
  57. _SCREENMOVE 100, 20
  58.  
  59. stars& = _LOADIMAGE("stars.png", 32)
  60. fnt& = _LOADFONT("ARLRDBD.ttf", 12, "MONOSPACE")
  61. _FONT fnt&
  62. COLOR &HFF00FFFF, &H00000000
  63. rocks& = 6 ' always active rocks
  64. lives& = 100
  65.  
  66. WHILE lives& AND _KEYDOWN(27) = 0 ' init start restart
  67.     FOR i = 1 TO nRocks 'reset rocks mainly clear baby rocks
  68.         newRock (i)
  69.         IF i > rocks& THEN r(i).live = 0
  70.     NEXT
  71.     ship.x = xmax / 2 'avoids explosions top left corner at start, dang still get some!
  72.     ship.y = ymax / 2
  73.     ship.live = 1
  74.     WHILE ship.live AND _KEYDOWN(27) = 0
  75.         'draw everything then process bullets
  76.         _PUTIMAGE , stars&
  77.         s$ = "Lives:" + STR$(lives&) + "  Hits:" + STR$(hits&) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits& * 100 / bullets)) + "%"
  78.         _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  79.         FOR i = 1 TO nRocks
  80.             IF r(i).live THEN drawRock i ' while drawing rocks the ship could be blown up
  81.         NEXT
  82.         FOR i = 1 TO nRocks 'smoke up the place with rock debris fields still flying out from hit frames ago
  83.             IF r(i).explodeFrame THEN
  84.                 r(i).explodeFrame = r(i).explodeFrame + 1
  85.                 IF r(i).explodeFrame > .5 * r(i).r THEN
  86.                     r(i).explodeFrame = 0
  87.                     IF i <= rocks& THEN newRock i ' now replace the rock
  88.                 ELSE
  89.                     explode r(i).x, r(i).y, r(i).r, r(i).explodeFrame
  90.                 END IF
  91.             END IF
  92.         NEXT
  93.         IF ship.live THEN
  94.             drawship
  95.             WHILE _MOUSEINPUT: WEND 'update ship
  96.             ship.x = _MOUSEX: ship.y = _MOUSEY
  97.             IF _MOUSEBUTTON(1) THEN ship.a = pi 'this is new left and right guns
  98.             IF _MOUSEBUTTON(2) THEN ship.a = 0
  99.             IF _KEYDOWN(ASC("w")) THEN ship.a = 1.5 * pi ' well it works but ??
  100.             IF _KEYDOWN(ASC("z")) THEN ship.a = .5 * pi
  101.             fire = 0
  102.             IF _KEYDOWN(32) THEN 'fire bullets
  103.                 t = TIMER(.01)
  104.                 IF lastt = 0 OR t - lastt > .2 THEN fire = 1: lastt = t: bullets = bullets + 1
  105.             END IF
  106.             FOR i = 0 TO nBullets 'handle bullets
  107.                 IF b(i).live = 0 AND fire = 1 THEN 'have inactive bullet to use
  108.                     b(i).x = ship.x + bSpeed * COS(ship.a)
  109.                     b(i).y = ship.y + bSpeed * SIN(ship.a)
  110.                     b(i).dx = bSpeed * COS(ship.a)
  111.                     b(i).dy = bSpeed * SIN(ship.a)
  112.                     b(i).live = -1
  113.                     fire = 0
  114.                 END IF
  115.                 IF b(i).live THEN 'new location
  116.                     b(i).x = b(i).x + b(i).dx
  117.                     b(i).y = b(i).y + b(i).dy
  118.                     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
  119.                         FOR r = 1 TO nRocks 'check for collision with rock
  120.                             IF r(r).live THEN
  121.                                 IF SQR((r(r).x - b(i).x) ^ 2 + (r(r).y - b(i).y) ^ 2) < r(r).r THEN 'its a hit!
  122.                                     r(r).explodeFrame = 1 'linger with explosion
  123.                                     r(r).live = 0
  124.                                     hits& = hits& + 1
  125.                                     IF r(r).r > 30 THEN '       split rock  into 2 new ones
  126.                                         '                        new rock
  127.                                         newRockN = freeRock& '                      get inactive rock number
  128.                                         newRock newRockN '                         new identity and activate
  129.                                         r(newRockN).r = (r(r).r - 10) / 2 '        split in half minus 20% mass
  130.                                         r(newRockN).x = r(r).x + irnd&(-10, 10) ' thrown from parent
  131.                                         r(newRockN).y = r(r).y + irnd&(-10, -1)
  132.                                         r(newRockN).c = r(r).c '                   same color as parent
  133.                                         r(newRockN).heading = rrnd(ship.a, ship.a + pi / 2)
  134.                                         '                        new rock again
  135.                                         newRockN = freeRock& '                      get inactive rock number
  136.                                         newRock newRockN '                         new identity and activate
  137.                                         r(newRockN).r = (r(r).r - 10) / 2 '        split in half minus 20% mass
  138.                                         r(newRockN).x = r(r).x + irnd&(-10, 10) ' thrown from parent
  139.                                         r(newRockN).y = r(r).y + irnd&(1, 10)
  140.                                         r(newRockN).c = r(r).c '                   same color as parent
  141.                                         r(newRockN).heading = rrnd(ship.a, ship.a - pi / 2)
  142.                                     END IF ' big enough to split
  143.                                     b(i).live = 0 'kill bullet
  144.                                 END IF ' hit rock
  145.                             END IF 'rock is there
  146.                         NEXT ' rock
  147.                         IF b(i).live THEN fcirc b(i).x, b(i).y, 3, _RGB32(255, 255, 0) 'draws bullet
  148.                     ELSE
  149.                         b(i).live = 0 'out of bounds
  150.                     END IF ' bullet is in bounds
  151.                 END IF ' bullet live
  152.             NEXT ' bullet
  153.         END IF ' if ship still live
  154.         _DISPLAY
  155.         IF ship.live = 0 THEN SLEEP ELSE _LIMIT 60 ' if ship dies let's rest and regroup  before restart next life
  156.     WEND
  157.     lives& = lives& - 1
  158.  
  159. FUNCTION freeRock&
  160.     DIM i AS LONG
  161.     FOR i = rocks& + 1 TO nRocks ' look for inactive rock number
  162.         IF r(i).live = 0 AND r(i).explodeFrame = 0 THEN freeRock& = i: EXIT FUNCTION
  163.     NEXT
  164.  
  165. SUB explode (x AS LONG, y AS LONG, r AS LONG, frm AS LONG)
  166.     DIM maxParticles AS LONG, i AS LONG, rounds AS LONG, loopCount AS LONG
  167.     maxParticles = r * 4
  168.     FOR i = 1 TO r
  169.         NewDot i, x, y, r
  170.     NEXT
  171.     rounds = r
  172.     FOR loopCount = 0 TO frm
  173.         IF _KEYDOWN(27) THEN END
  174.         FOR i = 1 TO rounds
  175.             dots(i).x = dots(i).x + dots(i).dx
  176.             dots(i).y = dots(i).y + dots(i).dy
  177.             fcirc dots(i).x, dots(i).y, dots(i).size, dots(i).kolor
  178.         NEXT
  179.         IF rounds < maxParticles THEN
  180.             FOR i = 1 TO r
  181.                 NewDot (rounds + i), x, y, r
  182.             NEXT
  183.             rounds = rounds + r
  184.         END IF
  185.     NEXT
  186.  
  187. SUB NewDot (i AS LONG, x AS LONG, y AS LONG, r AS LONG)
  188.     DIM angle, rd
  189.     angle = pi * 2 * RND
  190.     rd = RND * 30
  191.     dots(i).x = x + rd * COS(angle)
  192.     dots(i).y = y + rd * SIN(angle)
  193.     dots(i).size = RND * r * .05
  194.     rd = RND 'STxAxTIC recommended for rounder spreads
  195.     dots(i).dx = rd * 10 * (10 - 2 * dots(i).size) * COS(angle)
  196.     dots(i).dy = rd * 10 * (10 - 2 * dots(i).size) * SIN(angle)
  197.     rd = 20 + RND * 70
  198.     dots(i).kolor = _RGBA32(rd, rd, rd, 80)
  199.  
  200. SUB drawship 'simple red iso triangle pointed towards radianAngle
  201.     DIM x1 AS LONG, y1 AS LONG, x2 AS LONG, y2 AS LONG, x3 AS LONG, y3 AS LONG
  202.     'calculate 3 tail points of triangle ship
  203.     x1 = ship.x + 40 * COS(ship.a - pi) '   middle
  204.     y1 = ship.y + 40 * SIN(ship.a - pi) '
  205.     x2 = ship.x + 60 * COS(ship.a + .9 * pi) ' wing
  206.     y2 = ship.y + 60 * SIN(ship.a + .9 * pi)
  207.     x3 = ship.x + 60 * COS(ship.a - .9 * pi) ' other wing
  208.     y3 = ship.y + 60 * SIN(ship.a - .9 * pi)
  209.     ftri ship.x, ship.y, x1, y1, x2, y2, _RGB32(80, 120, 80, 80)
  210.     ftri ship.x, ship.y, x1, y1, x3, y3, _RGB32(60, 100, 60, 80)
  211.     LINE (ship.x, ship.y)-(x1, y1), _RGB32(255, 255, 128)
  212.     LINE (ship.x, ship.y)-(x2, y2), _RGB32(180, 180, 120)
  213.     LINE (ship.x, ship.y)-(x3, y3), _RGB32(180, 180, 120)
  214.  
  215. SUB drawRock (iRock)
  216.     RANDOMIZE USING r(iRock).seed 'this prevents having to save a particular sequence of random number
  217.     DIM dx, dy, rad AS LONG, 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
  218.     DIM x2 AS LONG, y2 AS LONG
  219.     dx = r(iRock).speed * COS(r(iRock).heading)
  220.     dy = r(iRock).speed * SIN(r(iRock).heading) 'update location
  221.     r(iRock).ra = r(iRock).ra + r(iRock).spin
  222.     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
  223.         IF iRock <= rocks& THEN newRock iRock ELSE r(iRock).live = 0
  224.         EXIT SUB ' reassigned get out of here
  225.     ELSE
  226.         r(iRock).x = r(iRock).x + dx
  227.         r(iRock).y = r(iRock).y + dy
  228.     END IF
  229.     IF ((r(iRock).x - ship.x) ^ 2 + (r(iRock).y - ship.y) ^ 2) ^ .5 < r(iRock).r + 30 THEN 'rock collides with ship?
  230.         FOR rad = 1 TO 200
  231.             fcirc ship.x, ship.y, rad, _RGB32(255 - rad, 255 - 2 * rad, 0)
  232.             _DISPLAY
  233.             _LIMIT 300
  234.         NEXT
  235.         ship.live = 0
  236.         lives& = lives& - 1
  237.         IF iRock <= rocks& THEN newRock iRock ELSE r(iRock).live = 0
  238.         EXIT SUB
  239.     END IF
  240.     FOR j = 10 TO 3 STEP -1 '                  rock drawing (see demo program where developed code)
  241.         rRad = .1 * j * r(iRock).r
  242.         leg = rRad * (RND * .7 + .3)
  243.         x0 = r(iRock).x + leg * COS(r(iRock).ra)
  244.         y0 = r(iRock).y + leg * SIN(r(iRock).ra)
  245.         rc = r(iRock).c + 30 * RND - 15
  246.         c~& = _RGB32(rc + 5, rc - 10, rc + 5)
  247.         x1 = x0
  248.         y1 = y0
  249.         xoff = RND * 20 - 10 + r(iRock).x
  250.         yoff = RND * 20 - 10 + r(iRock).y
  251.         FOR i = 1 TO 12
  252.             leg = rRad * (RND * .35 + .65)
  253.             IF i = 12 THEN
  254.                 x2 = x0: y2 = y0
  255.             ELSE
  256.                 x2 = xoff + leg * COS(i * polyAngle + r(iRock).ra)
  257.                 y2 = yoff + leg * SIN(i * polyAngle + r(iRock).ra)
  258.             END IF
  259.             ftri r(iRock).x, r(iRock).y, x1, y1, x2, y2, c~&
  260.             x1 = x2: y1 = y2
  261.         NEXT
  262.     NEXT
  263.  
  264. SUB newRock (iRock)
  265.     DIM side AS LONG
  266.     RANDOMIZE TIMER * RND 'to avoid making twins
  267.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  268.     SELECT CASE side
  269.         CASE 1
  270.             r(iRock).x = -10
  271.             r(iRock).y = rrnd(20, ymax - 20)
  272.             r(iRock).heading = 3 * pi / 2 + RND * pi
  273.         CASE 2
  274.             r(iRock).x = xmax + 10
  275.             r(iRock).y = rrnd(20, ymax - 20)
  276.             r(iRock).heading = pi / 2 + RND * pi
  277.         CASE 3
  278.             r(iRock).x = rrnd(20, xmax - 20)
  279.             r(iRock).y = -10
  280.             r(iRock).heading = RND * pi
  281.         CASE 4
  282.             r(iRock).x = rrnd(20, xmax - 20)
  283.             r(iRock).y = ymax + 10
  284.             r(iRock).heading = pi + RND * pi
  285.     END SELECT
  286.     r(iRock).speed = rrnd(2, 5) 'speed, rotation angle, radius, gray coloring, spin, seed, hit for explosion
  287.     r(iRock).ra = RND * 2 * pi
  288.     r(iRock).r = irnd&(30, 100)
  289.     r(iRock).c = irnd&(10, 60)
  290.     r(iRock).spin = rrnd(-pi / 20, pi / 20)
  291.     r(iRock).seed = INT(RND * 64000) - 32000
  292.     r(iRock).explodeFrame = 0
  293.     r(iRock).live = 1
  294.  
  295. FUNCTION irnd& (n1, n2) 'return an integer between 2 numbers
  296.     DIM l%, h%
  297.     IF n1 > n2 THEN l% = n2: h% = n1 ELSE l% = n1: h% = n2
  298.     irnd& = INT(RND * (h% - l% + 1)) + l%
  299.  
  300. FUNCTION rrnd (n1, n2) ' return number (expecting reals =_single, double, _float depending on default / define setup)
  301.     rrnd = (n2 - n1) * RND + n1
  302.  
  303. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  304.     DIM D AS LONG
  305.     STATIC a&
  306.     D = _DEST
  307.     IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32)
  308.     _DEST a&
  309.     _DONTBLEND a& '  '<<<< new 2019-12-16 fix
  310.     PSET (0, 0), K
  311.     _BLEND a& '<<<< new 2019-12-16 fix
  312.     _DEST D
  313.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  314.  
  315. SUB fcirc (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG) 'vince version
  316.     DIM x0 AS LONG, y0 AS LONG, e AS LONG
  317.     x0 = R: y0 = 0: e = 0
  318.     DO WHILE y0 < x0
  319.         IF e <= 0 THEN
  320.             y0 = y0 + 1
  321.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  322.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  323.             e = e + 2 * y0
  324.         ELSE
  325.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  326.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  327.             x0 = x0 - 1: e = e - 2 * x0
  328.         END IF
  329.     LOOP
  330.     LINE (x - R, y)-(x + R, y), C, BF
  331.  

I have to compare the first post to the current version.

Assets in zip first post.
Title: Re: b+ Asteroids makeover
Post by: SierraKen on October 30, 2020, 02:54:47 pm
AWESOME Explosions! I also really like your physics on the broken up asteroids, great job! The keys are a bit awkward for me though, I can use the mouse buttons and the W and Z keys, but is there any other keys? All of the Asteroids games I've ever played lets you rotate your ship in both directions to fire. But of course different is good too if you like this better. But you are doing an amazing job, better artist than I am on everything. :) 
Title: Re: b+ Asteroids makeover
Post by: FellippeHeitor on October 30, 2020, 03:32:02 pm
Very fun to play, bplus!
Title: Re: b+ Asteroids makeover
Post by: bplus on October 30, 2020, 04:23:27 pm
AWESOME Explosions! I also really like your physics on the broken up asteroids, great job! The keys are a bit awkward for me though, I can use the mouse buttons and the W and Z keys, but is there any other keys? All of the Asteroids games I've ever played lets you rotate your ship in both directions to fire. But of course different is good too if you like this better. But you are doing an amazing job, better artist than I am on everything. :)

Ken, check out eRATication 5 here is copy:
https://www.qb64.org/forum/index.php?topic=3164.msg124309#msg124309

The mouse/cheese wedge points in the direction you move the mouse, so the bullets are always headed the same direction you move the mouse. I would go with this method except! the point is so wobbly! too wobbly for any good aim and shoot even machine gun style. Try hitting the smaller rats.

I have not found a way to get rid of the wobbly, plus you have to move the point towards the thing you want to shoot at.

I am kind of liking the shooter here, flip the gun left and right, you know exactly where you're pointing when you shoot.

PS I don't recommend w, z I just put it there for... that WASDZ guy ;-))  I should do the other directions too.

Big fan of left hand space bar = fire!, right hand mouse = flipping gun with mouse buttons and driving the ship.
Title: Re: b+ Asteroids makeover
Post by: bplus on October 30, 2020, 04:29:54 pm
Very fun to play, bplus!

Good! that's what I am going for :)

Fun to blow up things. Say, should we try more little rocks?

Oh I was going to work out a points system: Highest Points for smallest, darkest, fastest rocks. Next to no points for giant, light, slow moving elephant like rocks.

And of course we have to invite some aliens over for war games ;-))
Title: Re: b+ Asteroids makeover
Post by: SierraKen on October 30, 2020, 04:40:42 pm
LOL I just tried your eRATication, I see your point about turning too fast. One thing you can try is instead of turning by the movement of your mouse, you can turn by turning your mouse wheel. One direction would go one way and the other direction could go another way. I'm sure you could figure it out. If you need help, get mine or your old clock codes and see how the second hand turns around the clock. If you want. :)
Title: Re: b+ Asteroids makeover
Post by: bplus on October 30, 2020, 04:47:05 pm
LOL I just tried your eRATication, I see your point about turning too fast. One thing you can try is instead of turning by the movement of your mouse, you can turn by turning your mouse wheel. One direction would go one way and the other direction could go another way. I'm sure you could figure it out. If you need help, get mine or your old clock codes and see how the second hand turns around the clock. If you want. :)

Oh yeah, let's try that! We can keep Left and Right guns and use wheel to fine tune.
Title: Re: b+ Asteroids makeover
Post by: bplus on October 30, 2020, 06:13:21 pm
w is up, z is down.

Now should it be a / d for left and right and leave s for shooting

or

leave space bar alone for shooting and use a / s for left and right?

I am unfamiliar with this system.

The _MOUSEWHEEL works great! Using pi/8 increments so you have all 90 and 45 degree angles covered plus one in between.
Title: Re: b+ Asteroids makeover
Post by: SierraKen on October 30, 2020, 06:23:20 pm
Sweet! I can't wait to play it. If you want to use the regular WASD keys, they are W = up, S = down, A = left, D = right. Z is really hard on the hands to use on a regular keyboard. X is OK for down if you want to use that, but the farther away the keys, the harder it is. I would use WASD.
Title: Re: b+ Asteroids makeover
Post by: bplus on October 30, 2020, 07:06:39 pm
Oh thanks, guess I was off!

Here Ken, this block is all that's changed at moment:
Code: QB64: [Select]
  1.             WHILE _MOUSEINPUT
  2.                 ship.a = ship.a + _MOUSEWHEEL * pi / 8 ' 22.5  degree changes, Thank Ken for this :)
  3.             WEND 'update ship
  4.             ship.x = _MOUSEX: ship.y = _MOUSEY
  5.             IF _MOUSEBUTTON(1) THEN ship.a = pi 'this is new left and right guns
  6.             IF _MOUSEBUTTON(2) THEN ship.a = 0
  7.             IF _KEYDOWN(ASC("w")) THEN ship.a = 1.5 * pi ' well it works but ??
  8.             IF _KEYDOWN(ASC("a")) THEN ship.a = pi
  9.             IF _KEYDOWN(ASC("s")) THEN ship.a = .5 * pi
  10.             IF _KEYDOWN(ASC("d")) THEN ship.a = 0
  11.  
Title: Re: b+ Asteroids makeover
Post by: SierraKen on October 30, 2020, 07:44:43 pm
LOL I love it! When you are ready to add sound, I would use small .mp3 explosion sounds, since QB64 can't access Windows drumset midi sounds, I wish it could, unless it's a library to access?
And like you said, another set of even smaller asteroids to shoot would be cool too, and the alien ship. :D This is coming out really good. It's like the old 90's games that added Windows behavior to 80's arcade games.
Title: Re: b+ Asteroids makeover
Post by: bplus on October 30, 2020, 11:18:03 pm
OK here are some more changes for today, more rocks potentially when hit a big one, Point system, increase level of difficulty, get stoned ending (speaking literally of course!).

Code: QB64: [Select]
  1. _TITLE "b+ Asteroids m3" 'started 2018-07-13"
  2. ' 2020-10-27 remove the alternate subs and get down below 200 LOC almost there now! new shooter action font and background
  3. ' 2020-10-28 another makeover explosions and split asteroids
  4. ' 2020-10-29 fix baby rock management, break between lives
  5. ' 2020-10-29 fix left/right gun, fix explosions over many frames to eliminate pause in action, speed up 60 fps
  6. ' 2020-10-30 m3 SierraKen's idea to angle shooter with mousewheel also finish WASD options, more rocks, points system
  7. ' points:
  8. ' The higher the speed the better    speed range 2 to 5, diff = 3 * 33.3333 = 100          s - 2 * 33.3333
  9. ' The lower the color the better   color range 10 to 60, diff =      50 * 2 = 100  50 - (c - 10) * 2
  10. ' The smaller the size the better  size range 10 to 100, diff = 90 * 1.1111 = 100  90 - (sz -10) * 1.1111
  11. '        ((speed - 2) * 33.3333 + (50 - (c -10)) * 2 + (90 - (r - 10)) * 1.1111) / 3 = 100 best score per hit
  12. ' 2020-10-30 increase level of difficulty, fix double lives lost, add an ending after all lives spent.
  13.  
  14. '================================================================================================================
  15.  
  16. '    NOTE: !!!!!!!!!!!!!!!   When there is a pause in action, just hit any key to reset next life.
  17.  
  18. '================================================================================================================
  19.  
  20. CONST xmax = 1200, ymax = 700, pi = _PI, polyAngle = _PI / 6, nRocks = 300, nBullets = 2000, bSpeed = 15
  21.  
  22. TYPE particle
  23.     x AS LONG
  24.     y AS LONG
  25.     dx AS SINGLE
  26.     dy AS SINGLE
  27.     size AS SINGLE
  28.     kolor AS _UNSIGNED LONG
  29.  
  30. TYPE bullet
  31.     x AS LONG
  32.     y AS LONG
  33.     dx AS SINGLE
  34.     dy AS SINGLE
  35.     live AS LONG
  36.  
  37. TYPE shipType
  38.     x AS LONG
  39.     y AS LONG
  40.     live AS LONG
  41.     a AS SINGLE '   rotated position usu gun left or right (mouse button), maybe up press w or down press z
  42.  
  43. TYPE rock
  44.     x AS LONG
  45.     y AS LONG
  46.     r AS LONG '            radius
  47.     ra AS SINGLE '         rotation position   a = a + spin
  48.     heading AS SINGLE '    heading from which dx, dy are calc with speed
  49.     speed AS SINGLE '      speed
  50.     spin AS SINGLE '       rotation direction and amount
  51.     seed AS LONG '         for drawing rocks with RND USING
  52.     c AS LONG '            color   rgb(c, c, c)
  53.     live AS LONG '         need this to track rocks still active like bullets
  54.     explodeFrame AS LONG ' after a rock is hit by bullet, it explodes and in more than one frame
  55.  
  56. DIM SHARED dots(2000) AS particle
  57. DIM SHARED b(nBullets) AS bullet
  58. DIM SHARED ship AS shipType
  59. DIM SHARED r(nRocks) AS rock
  60. DIM SHARED lives&, points&, rocks& 'rocks is the minimum number of parent rocks to have on screen  automatic replace when hit or out of bounds
  61. DIM i AS LONG, bullets AS LONG, fire AS LONG, stars&, fnt&, fnt2&, s$, hits&, t, lastt, r AS LONG, newRockN AS LONG, maxBabyRocks AS LONG, br AS LONG
  62.  
  63. SCREEN _NEWIMAGE(xmax, ymax, 32)
  64. _SCREENMOVE 100, 20
  65.  
  66. stars& = _LOADIMAGE("stars.png", 32)
  67. fnt& = _LOADFONT("ARLRDBD.ttf", 16, "MONOSPACE")
  68. fnt2& = _LOADFONT("ARLRDBD.ttf", 40, "MONOSPACE")
  69. _FONT fnt&
  70. COLOR &HFF00FFFF, &H00000000
  71. rocks& = 6 ' always active rocks
  72. lives& = 5
  73.  
  74. WHILE lives& > 0 AND _KEYDOWN(27) = 0 ' init start restart
  75.     FOR i = 1 TO nRocks 'reset rocks mainly clear baby rocks
  76.         newRock (i)
  77.         IF i > rocks& THEN r(i).live = 0
  78.     NEXT
  79.     ship.x = xmax / 2 'avoids explosions top left corner at start, dang still get some!
  80.     ship.y = ymax / 2
  81.     ship.live = 1
  82.     WHILE ship.live AND _KEYDOWN(27) = 0
  83.         'draw everything then process bullets
  84.         _PUTIMAGE , stars&
  85.         _FONT fnt&
  86.         s$ = "Lives:" + STR$(lives&) + "  Hits:" + STR$(hits&) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits& * 100 / bullets)) + "%"
  87.         _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 20), s$
  88.         _FONT fnt2&
  89.         s$ = STR$(points&)
  90.         _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  91.         FOR i = 1 TO nRocks
  92.             IF r(i).live THEN drawRock i ' while drawing rocks the ship could be blown up
  93.         NEXT
  94.         FOR i = 1 TO nRocks 'smoke up the place with rock debris fields still flying out from hit frames ago
  95.             IF r(i).explodeFrame THEN
  96.                 r(i).explodeFrame = r(i).explodeFrame + 1
  97.                 IF r(i).explodeFrame > .5 * r(i).r THEN
  98.                     r(i).explodeFrame = 0
  99.                     IF i <= rocks& THEN newRock i ' now replace the rock
  100.                 ELSE
  101.                     explode r(i).x, r(i).y, r(i).r, r(i).explodeFrame
  102.                 END IF
  103.             END IF
  104.         NEXT
  105.         IF ship.live THEN
  106.             drawship
  107.  
  108.             WHILE _MOUSEINPUT
  109.                 ship.a = ship.a + _MOUSEWHEEL * pi / 8 ' 22.5  degree changes, Thank Ken for this :)
  110.             WEND 'update ship
  111.             ship.x = _MOUSEX: ship.y = _MOUSEY
  112.             IF _MOUSEBUTTON(1) THEN ship.a = pi 'this is new left and right guns
  113.             IF _MOUSEBUTTON(2) THEN ship.a = 0
  114.             IF _KEYDOWN(ASC("w")) THEN ship.a = 1.5 * pi ' well it works but ??
  115.             IF _KEYDOWN(ASC("a")) THEN ship.a = pi
  116.             IF _KEYDOWN(ASC("s")) THEN ship.a = .5 * pi
  117.             IF _KEYDOWN(ASC("d")) THEN ship.a = 0
  118.             fire = 0
  119.             IF _KEYDOWN(32) THEN 'fire bullets
  120.                 t = TIMER(.01)
  121.                 IF lastt = 0 OR t - lastt > .2 THEN fire = 1: lastt = t
  122.             END IF
  123.             FOR i = 0 TO nBullets 'handle bullets
  124.                 IF b(i).live = 0 AND fire = 1 THEN 'have inactive bullet to use
  125.                     b(i).x = ship.x + bSpeed * COS(ship.a)
  126.                     b(i).y = ship.y + bSpeed * SIN(ship.a)
  127.                     b(i).dx = bSpeed * COS(ship.a)
  128.                     b(i).dy = bSpeed * SIN(ship.a)
  129.                     b(i).live = -1
  130.                     bullets = bullets + 1
  131.                     fire = 0
  132.                 END IF
  133.                 IF b(i).live THEN 'new location
  134.                     b(i).x = b(i).x + b(i).dx
  135.                     b(i).y = b(i).y + b(i).dy
  136.                     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
  137.                         FOR r = 1 TO nRocks 'check for collision with rock
  138.                             IF r(r).live THEN
  139.                                 IF SQR((r(r).x - b(i).x) ^ 2 + (r(r).y - b(i).y) ^ 2) < r(r).r THEN 'its a hit!
  140.                                     r(r).explodeFrame = 1 'linger with explosion
  141.                                     r(r).live = 0
  142.                                     hits& = hits& + 1
  143.                                     points& = points& + ((r(r).speed - 2) * 33.3333 + (50 - (r(r).c - 10)) * 2 + (90 - (r(r).r - 10)) * 1.1111) / 3
  144.                                     IF r(r).r > 30 THEN '       split rock  into ? new ones
  145.                                         maxBabyRocks = INT((r(r).r - 10) / 10)
  146.                                         maxBabyRocks = irnd&(2, maxBabyRocks) ' pick a number of baby Rocks
  147.                                         FOR br = 1 TO maxBabyRocks
  148.                                             '                        new rock
  149.                                             newRockN = freeRock& '                          get inactive rock number
  150.                                             newRock newRockN '                              new identity and activate
  151.                                             r(newRockN).r = (r(r).r - 10) / maxBabyRocks '  split in equal parts minus 20% mass
  152.                                             r(newRockN).x = r(r).x + irnd&(-30, 30) '       thrown from parent
  153.                                             r(newRockN).y = r(r).y + irnd&(-30, 30)
  154.                                             r(newRockN).c = r(r).c '                   same color as parent
  155.                                             r(newRockN).heading = rrnd(ship.a - .75 * pi, ship.a + .75 * pi)
  156.                                         NEXT
  157.                                     END IF ' big enough to split
  158.                                     b(i).live = 0 'kill bullet
  159.                                 END IF ' hit rock
  160.                             END IF 'rock is there
  161.                         NEXT ' rock
  162.                         IF b(i).live THEN fcirc b(i).x, b(i).y, 3, _RGB32(255, 255, 0) 'draws bullet
  163.                     ELSE
  164.                         b(i).live = 0 'out of bounds
  165.                     END IF ' bullet is in bounds
  166.                 END IF ' bullet live
  167.             NEXT ' bullet
  168.         END IF ' if ship still live
  169.         _DISPLAY
  170.         IF ship.live = 0 THEN SLEEP ELSE _LIMIT 60 ' if ship dies let's rest and regroup  before restart next life
  171.     WEND
  172.     lives& = lives& - 1
  173.     rocks& = rocks& + 1
  174. ship.x = -200: ship.y = -200 'get it out of the way
  175. WHILE rocks& < nRocks
  176.     _PUTIMAGE , stars&
  177.     rocks& = rocks& + 1
  178.     newRock rocks&
  179.     FOR r = 1 TO nRocks
  180.         drawRock r
  181.     NEXT
  182.     _FONT fnt&
  183.     s$ = "Lives:" + STR$(lives&) + "  Hits:" + STR$(hits&) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits& * 100 / bullets)) + "%"
  184.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 20), s$
  185.     _FONT fnt2&
  186.     s$ = STR$(points&)
  187.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  188.     _FONT fnt&
  189.     _DISPLAY
  190.     _LIMIT 30
  191.  
  192. FUNCTION freeRock&
  193.     DIM i AS LONG
  194.     FOR i = rocks& + 1 TO nRocks ' look for inactive rock number
  195.         IF r(i).live = 0 AND r(i).explodeFrame = 0 THEN freeRock& = i: EXIT FUNCTION
  196.     NEXT
  197.  
  198. SUB explode (x AS LONG, y AS LONG, r AS LONG, frm AS LONG)
  199.     DIM maxParticles AS LONG, i AS LONG, rounds AS LONG, loopCount AS LONG
  200.     maxParticles = r * 4
  201.     FOR i = 1 TO r
  202.         NewDot i, x, y, r
  203.     NEXT
  204.     rounds = r
  205.     FOR loopCount = 0 TO frm
  206.         IF _KEYDOWN(27) THEN END
  207.         FOR i = 1 TO rounds
  208.             dots(i).x = dots(i).x + dots(i).dx
  209.             dots(i).y = dots(i).y + dots(i).dy
  210.             fcirc dots(i).x, dots(i).y, dots(i).size, dots(i).kolor
  211.         NEXT
  212.         IF rounds < maxParticles THEN
  213.             FOR i = 1 TO r
  214.                 NewDot (rounds + i), x, y, r
  215.             NEXT
  216.             rounds = rounds + r
  217.         END IF
  218.     NEXT
  219.  
  220. SUB NewDot (i AS LONG, x AS LONG, y AS LONG, r AS LONG)
  221.     DIM angle, rd
  222.     angle = pi * 2 * RND
  223.     rd = RND * 30
  224.     dots(i).x = x + rd * COS(angle)
  225.     dots(i).y = y + rd * SIN(angle)
  226.     dots(i).size = RND * r * .05
  227.     rd = RND 'STxAxTIC recommended for rounder spreads
  228.     dots(i).dx = rd * 10 * (10 - 2 * dots(i).size) * COS(angle)
  229.     dots(i).dy = rd * 10 * (10 - 2 * dots(i).size) * SIN(angle)
  230.     rd = 20 + RND * 70
  231.     dots(i).kolor = _RGBA32(rd, rd, rd, 80)
  232.  
  233. SUB drawship 'simple red iso triangle pointed towards radianAngle
  234.     DIM x1 AS LONG, y1 AS LONG, x2 AS LONG, y2 AS LONG, x3 AS LONG, y3 AS LONG
  235.     'calculate 3 tail points of triangle ship
  236.     x1 = ship.x + 40 * COS(ship.a - pi) '   middle
  237.     y1 = ship.y + 40 * SIN(ship.a - pi) '
  238.     x2 = ship.x + 60 * COS(ship.a + .9 * pi) ' wing
  239.     y2 = ship.y + 60 * SIN(ship.a + .9 * pi)
  240.     x3 = ship.x + 60 * COS(ship.a - .9 * pi) ' other wing
  241.     y3 = ship.y + 60 * SIN(ship.a - .9 * pi)
  242.     ftri ship.x, ship.y, x1, y1, x2, y2, _RGB32(80, 120, 80, 80)
  243.     ftri ship.x, ship.y, x1, y1, x3, y3, _RGB32(60, 100, 60, 80)
  244.     LINE (ship.x, ship.y)-(x1, y1), _RGB32(255, 255, 128)
  245.     LINE (ship.x, ship.y)-(x2, y2), _RGB32(180, 180, 120)
  246.     LINE (ship.x, ship.y)-(x3, y3), _RGB32(180, 180, 120)
  247.  
  248. SUB drawRock (iRock)
  249.     RANDOMIZE USING r(iRock).seed 'this prevents having to save a particular sequence of random number
  250.     DIM dx, dy, rad AS LONG, 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
  251.     DIM x2 AS LONG, y2 AS LONG
  252.     dx = r(iRock).speed * COS(r(iRock).heading)
  253.     dy = r(iRock).speed * SIN(r(iRock).heading) 'update location
  254.     r(iRock).ra = r(iRock).ra + r(iRock).spin
  255.     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
  256.         IF iRock <= rocks& THEN newRock iRock ELSE r(iRock).live = 0
  257.         EXIT SUB ' reassigned get out of here
  258.     ELSE
  259.         r(iRock).x = r(iRock).x + dx
  260.         r(iRock).y = r(iRock).y + dy
  261.     END IF
  262.     IF ((r(iRock).x - ship.x) ^ 2 + (r(iRock).y - ship.y) ^ 2) ^ .5 < r(iRock).r + 30 THEN 'rock collides with ship?
  263.         FOR rad = 1 TO 200
  264.             fcirc ship.x, ship.y, rad, _RGB32(255 - rad, 255 - 2 * rad, 0)
  265.             _DISPLAY
  266.             _LIMIT 300
  267.         NEXT
  268.         ship.live = 0
  269.         IF iRock <= rocks& THEN newRock iRock ELSE r(iRock).live = 0
  270.         EXIT SUB
  271.     END IF
  272.     FOR j = 10 TO 3 STEP -1 '                  rock drawing (see demo program where developed code)
  273.         rRad = .1 * j * r(iRock).r
  274.         leg = rRad * (RND * .7 + .3)
  275.         x0 = r(iRock).x + leg * COS(r(iRock).ra)
  276.         y0 = r(iRock).y + leg * SIN(r(iRock).ra)
  277.         rc = r(iRock).c + 30 * RND - 15
  278.         c~& = _RGB32(rc + 5, rc - 10, rc + 5)
  279.         x1 = x0
  280.         y1 = y0
  281.         xoff = RND * 20 - 10 + r(iRock).x
  282.         yoff = RND * 20 - 10 + r(iRock).y
  283.         FOR i = 1 TO 12
  284.             leg = rRad * (RND * .35 + .65)
  285.             IF i = 12 THEN
  286.                 x2 = x0: y2 = y0
  287.             ELSE
  288.                 x2 = xoff + leg * COS(i * polyAngle + r(iRock).ra)
  289.                 y2 = yoff + leg * SIN(i * polyAngle + r(iRock).ra)
  290.             END IF
  291.             ftri r(iRock).x, r(iRock).y, x1, y1, x2, y2, c~&
  292.             x1 = x2: y1 = y2
  293.         NEXT
  294.     NEXT
  295.  
  296. SUB newRock (iRock)
  297.     DIM side AS LONG
  298.     RANDOMIZE TIMER * RND 'to avoid making twins
  299.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  300.     SELECT CASE side
  301.         CASE 1
  302.             r(iRock).x = -10
  303.             r(iRock).y = rrnd(20, ymax - 20)
  304.             r(iRock).heading = 3 * pi / 2 + RND * pi
  305.         CASE 2
  306.             r(iRock).x = xmax + 10
  307.             r(iRock).y = rrnd(20, ymax - 20)
  308.             r(iRock).heading = pi / 2 + RND * pi
  309.         CASE 3
  310.             r(iRock).x = rrnd(20, xmax - 20)
  311.             r(iRock).y = -10
  312.             r(iRock).heading = RND * pi
  313.         CASE 4
  314.             r(iRock).x = rrnd(20, xmax - 20)
  315.             r(iRock).y = ymax + 10
  316.             r(iRock).heading = pi + RND * pi
  317.     END SELECT
  318.     r(iRock).speed = rrnd(2, 5) 'speed, rotation angle, radius, gray coloring, spin, seed, hit for explosion
  319.     r(iRock).ra = RND * 2 * pi
  320.     r(iRock).r = irnd&(30, 100)
  321.     r(iRock).c = irnd&(10, 60)
  322.     r(iRock).spin = rrnd(-pi / 20, pi / 20)
  323.     r(iRock).seed = INT(RND * 64000) - 32000
  324.     r(iRock).explodeFrame = 0
  325.     r(iRock).live = 1
  326.  
  327. FUNCTION irnd& (n1, n2) 'return an integer between 2 numbers
  328.     DIM l%, h%
  329.     IF n1 > n2 THEN l% = n2: h% = n1 ELSE l% = n1: h% = n2
  330.     irnd& = INT(RND * (h% - l% + 1)) + l%
  331.  
  332. FUNCTION rrnd (n1, n2) ' return number (expecting reals =_single, double, _float depending on default / define setup)
  333.     rrnd = (n2 - n1) * RND + n1
  334.  
  335. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  336.     DIM D AS LONG
  337.     STATIC a&
  338.     D = _DEST
  339.     IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32)
  340.     _DEST a&
  341.     _DONTBLEND a& '  '<<<< new 2019-12-16 fix
  342.     PSET (0, 0), K
  343.     _BLEND a& '<<<< new 2019-12-16 fix
  344.     _DEST D
  345.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  346.  
  347. SUB fcirc (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG) 'vince version
  348.     DIM x0 AS LONG, y0 AS LONG, e AS LONG
  349.     x0 = R: y0 = 0: e = 0
  350.     DO WHILE y0 < x0
  351.         IF e <= 0 THEN
  352.             y0 = y0 + 1
  353.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  354.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  355.             e = e + 2 * y0
  356.         ELSE
  357.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  358.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  359.             x0 = x0 - 1: e = e - 2 * x0
  360.         END IF
  361.     LOOP
  362.     LINE (x - R, y)-(x + R, y), C, BF
  363.  
Title: Re: b+ Asteroids makeover
Post by: SierraKen on October 30, 2020, 11:47:49 pm
Works great! I like the smaller asteroids. I hope others play this too, it's amazing.
Title: Re: b+ Asteroids makeover
Post by: bplus on November 01, 2020, 01:04:20 am
Happy Halloween! The aliens have accepted my invitation to come play war games. One moment they are just another spaceship, the next they are transformed into The Bolder of Death.

Code: QB64: [Select]
  1. _TITLE "b+ Asteroids m4 They are Here" 'started 2018-07-13"
  2. ' 2020-10-27 remove the alternate subs and get down below 200 LOC almost there now! new shooter action font and background
  3. ' 2020-10-28 another makeover explosions and split asteroids
  4. ' 2020-10-29 fix baby rock management, break between lives
  5. ' 2020-10-29 fix left/right gun, fix explosions over many frames to eliminate pause in action, speed up 60 fps
  6. ' 2020-10-30 m3 SierraKen's idea to angle shooter with mousewheel also finish WASD options, more rocks, points system
  7. ' points:
  8. ' The higher the speed the better    speed range 2 to 5, diff = 3 * 33.3333 = 100          s - 2 * 33.3333
  9. ' The lower the color the better   color range 10 to 60, diff =      50 * 2 = 100  50 - (c - 10) * 2
  10. ' The smaller the size the better  size range 10 to 100, diff = 90 * 1.1111 = 100  90 - (sz -10) * 1.1111
  11. '        ((speed - 2) * 33.3333 + (50 - (c -10)) * 2 + (90 - (r - 10)) * 1.1111) / 3 = 100 best score per hit
  12. ' 2020-10-30 increase level of difficulty, fix double lives lost, add an ending after all lives spent.
  13. ' 2020-10-31 M4 They are Here - the aliens have accepted my invitaion for war games don't get caught in their beam.
  14. ' rework ending and variable LONG suffix. Aliens on the attack 100 points before or after transformed into the Bolder of Death.
  15.  
  16. '================================================================================================================
  17.  
  18. '    NOTE: !!!!!!!!!!!!!!!   When there is a pause in action, just hit any key to reset next life.
  19.  
  20. '================================================================================================================
  21.  
  22. CONST xmax = 1200, ymax = 700, pi = _PI, polyAngle = _PI / 6, nRocks = 300, nBullets = 2000, bSpeed = 15
  23.  
  24. TYPE alienType
  25.     x AS SINGLE
  26.     y AS SINGLE
  27.     dx AS SINGLE
  28.     dy AS SINGLE
  29.     live AS LONG
  30.     attackFrame AS LONG
  31.     fireX AS LONG
  32.     fireY AS LONG
  33.     transform AS LONG
  34.  
  35. TYPE particle
  36.     x AS LONG
  37.     y AS LONG
  38.     dx AS SINGLE
  39.     dy AS SINGLE
  40.     size AS SINGLE
  41.     kolor AS _UNSIGNED LONG
  42.  
  43. TYPE bullet
  44.     x AS LONG
  45.     y AS LONG
  46.     dx AS SINGLE
  47.     dy AS SINGLE
  48.     live AS LONG
  49.  
  50. TYPE shipType
  51.     x AS LONG
  52.     y AS LONG
  53.     live AS LONG
  54.     a AS SINGLE '   rotated position usu gun left or right (mouse button), maybe up press w or down press z
  55.  
  56. TYPE rock
  57.     x AS LONG
  58.     y AS LONG
  59.     r AS LONG '            radius
  60.     ra AS SINGLE '         rotation position   a = a + spin
  61.     heading AS SINGLE '    heading from which dx, dy are calc with speed
  62.     speed AS SINGLE '      speed
  63.     spin AS SINGLE '       rotation direction and amount
  64.     seed AS LONG '         for drawing rocks with RND USING
  65.     c AS LONG '            color   rgb(c, c, c)
  66.     live AS LONG '         need this to track rocks still active like bullets
  67.     explodeFrame AS LONG ' after a rock is hit by bullet, it explodes and in more than one frame
  68.  
  69. DIM SHARED aliens AS alienType
  70. DIM SHARED dots(2000) AS particle
  71. DIM SHARED b(nBullets) AS bullet
  72. DIM SHARED ship AS shipType
  73. DIM SHARED r(nRocks) AS rock
  74. DIM SHARED points AS LONG
  75. 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
  76.  
  77. DIM stars AS LONG, fnt AS LONG, fnt2 AS LONG ' file LOAD handles
  78. DIM i AS LONG, bullets AS LONG, fire AS LONG ' index and bullets
  79. DIM r AS LONG, newRockN AS LONG, maxBabyRocks AS LONG, br AS LONG, hits AS LONG ' rock stuff
  80. DIM s$, t, lastt ' general string and times
  81.  
  82. SCREEN _NEWIMAGE(xmax, ymax, 32)
  83. _SCREENMOVE 100, 20
  84.  
  85. stars = _LOADIMAGE("stars.png", 32)
  86. fnt = _LOADFONT("ARLRDBD.ttf", 16, "MONOSPACE")
  87. fnt2 = _LOADFONT("ARLRDBD.ttf", 40, "MONOSPACE")
  88. _FONT fnt
  89. COLOR &HFF00FFFF, &H00000000
  90.  
  91. rocks = 3 ' always active rocks
  92. lives = 5
  93. WHILE lives > 0 AND _KEYDOWN(27) = 0 ' init start restart
  94.     newAlien
  95.     FOR i = 1 TO nRocks 'reset rocks mainly clear baby rocks
  96.         newRock (i)
  97.         IF i > rocks THEN r(i).live = 0
  98.     NEXT
  99.     ship.x = xmax / 2 'avoids explosions top left corner at start, dang still get some!
  100.     ship.y = ymax / 2
  101.     ship.live = 1
  102.     WHILE ship.live AND _KEYDOWN(27) = 0
  103.         'draw everything then process bullets
  104.         _PUTIMAGE , stars
  105.         '   CIRCLE (aliens.fireX, aliens.fireY), 10, &HFFFFFFFF   transformtion poimt Bolder of Death
  106.         s$ = "Lives:" + STR$(lives) + "  Hits:" + STR$(hits) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits * 100 / bullets)) + "%"
  107.         _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 20), s$
  108.         _FONT fnt2
  109.         s$ = STR$(points)
  110.         _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  111.         _FONT fnt
  112.         drawAliens
  113.         FOR i = 1 TO nRocks
  114.             IF r(i).live THEN drawRock i ' while drawing rocks the ship could be blown up
  115.         NEXT
  116.         FOR i = 1 TO nRocks 'smoke up the place with rock debris fields still flying out from hit frames ago
  117.             IF r(i).explodeFrame THEN
  118.                 r(i).explodeFrame = r(i).explodeFrame + 1
  119.                 IF r(i).explodeFrame > .5 * r(i).r THEN
  120.                     r(i).explodeFrame = 0
  121.                     IF i <= rocks THEN newRock i ' now replace the rock
  122.                 ELSE
  123.                     explode r(i).x, r(i).y, r(i).r, r(i).explodeFrame
  124.                 END IF
  125.             END IF
  126.         NEXT
  127.         IF ship.live THEN
  128.             IF SQR((aliens.x - ship.x) ^ 2 + (aliens.y - ship.y) ^ 2) < 60 THEN 'aliens and ship collisde boom boom
  129.                 FOR br = 1 TO 200
  130.                     fcirc ship.x, ship.y, br, _RGB32(255 - br, 255 - 2 * br, 0)
  131.                     _DISPLAY
  132.                     _LIMIT 300
  133.                 NEXT
  134.                 ship.live = 0
  135.                 _CONTINUE
  136.             ELSE
  137.                 drawship
  138.             END IF
  139.             WHILE _MOUSEINPUT
  140.                 ship.a = ship.a + _MOUSEWHEEL * pi / 8 ' 22.5  degree changes, Thank Ken for this :)
  141.             WEND 'update ship
  142.             ship.x = _MOUSEX: ship.y = _MOUSEY
  143.             IF _MOUSEBUTTON(1) THEN ship.a = pi 'this is new left and right guns
  144.             IF _MOUSEBUTTON(2) THEN ship.a = 0
  145.             IF _KEYDOWN(ASC("w")) THEN ship.a = 1.5 * pi ' well it works but ??
  146.             IF _KEYDOWN(ASC("a")) THEN ship.a = pi
  147.             IF _KEYDOWN(ASC("s")) THEN ship.a = .5 * pi
  148.             IF _KEYDOWN(ASC("d")) THEN ship.a = 0
  149.             fire = 0
  150.             IF _KEYDOWN(32) THEN 'fire bullets
  151.                 t = TIMER(.01)
  152.                 IF lastt = 0 OR t - lastt > .2 THEN fire = 1: lastt = t
  153.             END IF
  154.             FOR i = 0 TO nBullets 'handle bullets
  155.                 IF b(i).live = 0 AND fire = 1 THEN 'have inactive bullet to use
  156.                     b(i).x = ship.x + bSpeed * COS(ship.a)
  157.                     b(i).y = ship.y + bSpeed * SIN(ship.a)
  158.                     b(i).dx = bSpeed * COS(ship.a)
  159.                     b(i).dy = bSpeed * SIN(ship.a)
  160.                     b(i).live = -1
  161.                     bullets = bullets + 1
  162.                     fire = 0
  163.                 END IF
  164.                 IF b(i).live THEN 'new location
  165.                     b(i).x = b(i).x + b(i).dx
  166.                     b(i).y = b(i).y + b(i).dy
  167.                     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
  168.  
  169.                         'bullet hit aliens?
  170.  
  171.                         IF SQR((aliens.x - b(i).x) ^ 2 + (aliens.y - b(i).y) ^ 2) < 30 THEN
  172.                             FOR br = 1 TO 120
  173.                                 CIRCLE (aliens.x, aliens.y), br / 3, plasma~&(0)
  174.                             NEXT
  175.                             _DISPLAY
  176.                             _DELAY .3
  177.                             aliens.live = 0
  178.                             newAlien
  179.                             points = points + 100
  180.                             b(i).live = 0
  181.                             _CONTINUE
  182.                         END IF
  183.  
  184.                         FOR r = 1 TO nRocks 'check for collision with rock
  185.                             IF r(r).live THEN
  186.                                 IF SQR((r(r).x - b(i).x) ^ 2 + (r(r).y - b(i).y) ^ 2) < r(r).r THEN 'its a hit!
  187.                                     r(r).explodeFrame = 1 'linger with explosion
  188.                                     r(r).live = 0
  189.                                     hits = hits + 1
  190.                                     points = points + ((r(r).speed - 2) * 33.3333 + (50 - (r(r).c - 10)) * 2 + (90 - (r(r).r - 10)) * 1.1111) / 3
  191.                                     IF r(r).r > 30 THEN '       split rock  into ? new ones
  192.                                         maxBabyRocks = INT((r(r).r - 10) / 10)
  193.                                         maxBabyRocks = irnd&(2, maxBabyRocks) ' pick a number of baby Rocks
  194.                                         FOR br = 1 TO maxBabyRocks
  195.                                             '                        new rock
  196.                                             newRockN = freeRock& '                          get inactive rock number
  197.                                             newRock newRockN '                              new identity and activate
  198.                                             r(newRockN).r = (r(r).r - 10) / maxBabyRocks '  split in equal parts minus 20% mass
  199.                                             r(newRockN).x = r(r).x + irnd&(-30, 30) '       thrown from parent
  200.                                             r(newRockN).y = r(r).y + irnd&(-30, 30)
  201.                                             r(newRockN).c = r(r).c '                   same color as parent
  202.                                             r(newRockN).heading = rrnd(ship.a - .75 * pi, ship.a + .75 * pi)
  203.                                         NEXT
  204.                                     END IF ' big enough to split
  205.                                     b(i).live = 0 'kill bullet
  206.                                 END IF ' hit rock
  207.                             END IF 'rock is there
  208.                         NEXT ' rock
  209.                         IF b(i).live THEN fcirc b(i).x, b(i).y, 3, _RGB32(255, 255, 0) 'draws bullet
  210.                     ELSE
  211.                         b(i).live = 0 'out of bounds
  212.                     END IF ' bullet is in bounds
  213.                 END IF ' bullet live
  214.             NEXT ' bullet
  215.         END IF ' if ship still live
  216.         _DISPLAY
  217.         IF ship.live = 0 THEN SLEEP ELSE _LIMIT 60 ' if ship dies let's rest and regroup  before restart next life
  218.     WEND
  219.     lives = lives - 1
  220.     rocks = rocks + 1
  221. ship.x = -200: ship.y = -200 'get it out of the way
  222. i = 0
  223. WHILE _KEYDOWN(ASC("q")) = 0
  224.     _PUTIMAGE , stars
  225.     i = i + 1
  226.     IF i MOD 30 = 29 AND rocks < nRocks THEN rocks = rocks + 1: r(rocks).live = 1
  227.     FOR r = 1 TO nRocks
  228.         IF r(r).live THEN drawRock r
  229.     NEXT
  230.     s$ = "Lives:" + STR$(lives) + "  Hits:" + STR$(hits) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits * 100 / bullets)) + "%"
  231.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 20), s$
  232.     _FONT fnt2
  233.     s$ = STR$(points)
  234.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  235.     _FONT fnt
  236.     s$ = "Press q to quit"
  237.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 + 100), s$
  238.     _DISPLAY
  239.     _LIMIT 60
  240.  
  241. SUB newAlien
  242.     DIM side AS LONG, heading
  243.     RANDOMIZE TIMER * RND 'to avoid making twins
  244.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  245.     aliens.fireX = irnd(10, xmax - 10)
  246.     aliens.fireY = irnd(10, ymax - 10)
  247.     aliens.attackFrame = irnd(5, 30)
  248.     SELECT CASE side
  249.         CASE 1
  250.             aliens.x = -10
  251.             aliens.y = rrnd(20, ymax - 20)
  252.         CASE 2
  253.             aliens.x = xmax + 10
  254.             aliens.y = rrnd(20, ymax - 20)
  255.         CASE 3
  256.             aliens.x = rrnd(20, xmax - 20)
  257.             aliens.y = -10
  258.         CASE 4
  259.             aliens.x = rrnd(20, xmax - 20)
  260.             aliens.y = ymax + 10
  261.     END SELECT
  262.     heading = _ATAN2(aliens.fireY - aliens.y, aliens.fireX - aliens.x)
  263.     aliens.dx = 3.5 * COS(heading)
  264.     aliens.dy = 3.5 * SIN(heading)
  265.     aliens.live = 0
  266.     aliens.transform = 0
  267.  
  268. FUNCTION plasma~& (new AS LONG)
  269.     STATIC r, g, b, cnt, beenHere
  270.     IF beenHere = 0 OR new THEN
  271.         r = RND: g = RND: b = RND: beenHere = 1: cnt = 0
  272.     END IF
  273.     cnt = cnt + .2
  274.     plasma~& = _RGB32(127 + 127 * SIN(r * cnt), 127 + 127 * SIN(g * cnt), 127 + 127 * SIN(b * cnt))
  275.  
  276. SUB drawAliens 'shipType
  277.     STATIC ls AS LONG
  278.     DIM light AS LONG, heading
  279.  
  280.     IF aliens.live THEN
  281.         IF aliens.transform = 0 THEN
  282.             fellipse aliens.x, aliens.y, 6, 15, _RGB32(110, 20, 0)
  283.             fellipse aliens.x, aliens.y, 18, 11, _RGB32(150, 60, 0)
  284.             fellipse aliens.x, aliens.y, 30, 7, _RGB32(190, 100, 20)
  285.             FOR light = 1 TO 12
  286.                 fcirc aliens.x - 35 + 5 * light + ls, aliens.y, 1, _RGB32(ls * 20 + 150, ls * 20 + 150, ls * 20 + 150)
  287.             NEXT
  288.             ls = ls + 1
  289.             IF ls > 5 THEN ls = 0
  290.         ELSE
  291.             fcirc aliens.x, aliens.y, 30, &HFFFFFF00
  292.         END IF
  293.         'time to shoot?
  294.         aliens.x = aliens.x + aliens.dx
  295.         aliens.y = aliens.y + aliens.dy
  296.         IF SQR((aliens.fireX - aliens.x) ^ 2 + (aliens.fireY - aliens.y) ^ 2) < 5 THEN 'transform into the bolder of death
  297.             aliens.transform = 1
  298.             heading = _ATAN2(ship.y - aliens.y, ship.x - aliens.x)
  299.             aliens.dx = 10 * COS(heading)
  300.             aliens.dy = 10 * SIN(heading)
  301.         END IF
  302.         IF aliens.x < -10 OR aliens.x > xmax + 10 THEN
  303.             IF aliens.y < -10 OR aliens.y > ymax + 10 THEN '  out of bounds goodbye bolder of death!
  304.                 aliens.live = 0 'man we dodged a bullet here!!!!
  305.                 newAlien 'reset the trap
  306.             END IF
  307.         END IF
  308.     ELSE
  309.         IF aliens.attackFrame THEN
  310.             aliens.attackFrame = aliens.attackFrame - 1
  311.             IF aliens.attackFrame = 0 THEN
  312.                 aliens.live = 1
  313.             END IF
  314.         END IF
  315.     END IF
  316.  
  317. FUNCTION freeRock&
  318.     DIM i AS LONG
  319.     FOR i = rocks + 1 TO nRocks ' look for inactive rock number
  320.         IF r(i).live = 0 AND r(i).explodeFrame = 0 THEN freeRock& = i: EXIT FUNCTION
  321.     NEXT
  322.  
  323. SUB explode (x AS LONG, y AS LONG, r AS LONG, frm AS LONG)
  324.     DIM maxParticles AS LONG, i AS LONG, rounds AS LONG, loopCount AS LONG
  325.     maxParticles = r * 4
  326.     FOR i = 1 TO r
  327.         NewDot i, x, y, r
  328.     NEXT
  329.     rounds = r
  330.     FOR loopCount = 0 TO frm
  331.         IF _KEYDOWN(27) THEN END
  332.         FOR i = 1 TO rounds
  333.             dots(i).x = dots(i).x + dots(i).dx
  334.             dots(i).y = dots(i).y + dots(i).dy
  335.             fcirc dots(i).x, dots(i).y, dots(i).size, dots(i).kolor
  336.         NEXT
  337.         IF rounds < maxParticles THEN
  338.             FOR i = 1 TO r
  339.                 NewDot (rounds + i), x, y, r
  340.             NEXT
  341.             rounds = rounds + r
  342.         END IF
  343.     NEXT
  344.  
  345. SUB NewDot (i AS LONG, x AS LONG, y AS LONG, r AS LONG)
  346.     DIM angle, rd
  347.     angle = pi * 2 * RND
  348.     rd = RND * 30
  349.     dots(i).x = x + rd * COS(angle)
  350.     dots(i).y = y + rd * SIN(angle)
  351.     dots(i).size = RND * r * .05
  352.     rd = RND 'STxAxTIC recommended for rounder spreads
  353.     dots(i).dx = rd * 10 * (10 - 2 * dots(i).size) * COS(angle)
  354.     dots(i).dy = rd * 10 * (10 - 2 * dots(i).size) * SIN(angle)
  355.     rd = 20 + RND * 70
  356.     dots(i).kolor = _RGBA32(rd, rd, rd, 80)
  357.  
  358. SUB drawship 'simple red iso triangle pointed towards radianAngle
  359.     DIM x1 AS LONG, y1 AS LONG, x2 AS LONG, y2 AS LONG, x3 AS LONG, y3 AS LONG
  360.     'calculate 3 tail points of triangle ship
  361.     x1 = ship.x + 40 * COS(ship.a - pi) '   middle
  362.     y1 = ship.y + 40 * SIN(ship.a - pi) '
  363.     x2 = ship.x + 60 * COS(ship.a + .9 * pi) ' wing
  364.     y2 = ship.y + 60 * SIN(ship.a + .9 * pi)
  365.     x3 = ship.x + 60 * COS(ship.a - .9 * pi) ' other wing
  366.     y3 = ship.y + 60 * SIN(ship.a - .9 * pi)
  367.     ftri ship.x, ship.y, x1, y1, x2, y2, _RGB32(80, 120, 80, 80)
  368.     ftri ship.x, ship.y, x1, y1, x3, y3, _RGB32(60, 100, 60, 80)
  369.     LINE (ship.x, ship.y)-(x1, y1), _RGB32(255, 255, 128)
  370.     LINE (ship.x, ship.y)-(x2, y2), _RGB32(180, 180, 120)
  371.     LINE (ship.x, ship.y)-(x3, y3), _RGB32(180, 180, 120)
  372.  
  373. SUB drawRock (iRock)
  374.     RANDOMIZE USING r(iRock).seed 'this prevents having to save a particular sequence of random number
  375.     DIM dx, dy, rad AS LONG, 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
  376.     DIM x2 AS LONG, y2 AS LONG
  377.     dx = r(iRock).speed * COS(r(iRock).heading)
  378.     dy = r(iRock).speed * SIN(r(iRock).heading) 'update location
  379.     r(iRock).ra = r(iRock).ra + r(iRock).spin
  380.     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
  381.         IF iRock <= rocks THEN newRock iRock ELSE r(iRock).live = 0
  382.         EXIT SUB ' reassigned get out of here
  383.     ELSE
  384.         r(iRock).x = r(iRock).x + dx
  385.         r(iRock).y = r(iRock).y + dy
  386.     END IF
  387.     IF ((r(iRock).x - ship.x) ^ 2 + (r(iRock).y - ship.y) ^ 2) ^ .5 < r(iRock).r + 30 THEN 'rock collides with ship?
  388.         FOR rad = 1 TO 200
  389.             fcirc ship.x, ship.y, rad, _RGB32(255 - rad, 255 - 2 * rad, 0)
  390.             _DISPLAY
  391.             _LIMIT 300
  392.         NEXT
  393.         ship.live = 0
  394.         IF iRock <= rocks THEN newRock iRock ELSE r(iRock).live = 0
  395.         EXIT SUB
  396.     END IF
  397.     FOR j = 10 TO 3 STEP -1 '                  rock drawing (see demo program where developed code)
  398.         rRad = .1 * j * r(iRock).r
  399.         leg = rRad * (RND * .7 + .3)
  400.         x0 = r(iRock).x + leg * COS(r(iRock).ra)
  401.         y0 = r(iRock).y + leg * SIN(r(iRock).ra)
  402.         rc = r(iRock).c + 30 * RND - 15
  403.         c~& = _RGB32(rc + 5, rc - 10, rc + 5)
  404.         x1 = x0
  405.         y1 = y0
  406.         xoff = RND * 20 - 10 + r(iRock).x
  407.         yoff = RND * 20 - 10 + r(iRock).y
  408.         FOR i = 1 TO 12
  409.             leg = rRad * (RND * .35 + .65)
  410.             IF i = 12 THEN
  411.                 x2 = x0: y2 = y0
  412.             ELSE
  413.                 x2 = xoff + leg * COS(i * polyAngle + r(iRock).ra)
  414.                 y2 = yoff + leg * SIN(i * polyAngle + r(iRock).ra)
  415.             END IF
  416.             ftri r(iRock).x, r(iRock).y, x1, y1, x2, y2, c~&
  417.             x1 = x2: y1 = y2
  418.         NEXT
  419.     NEXT
  420.  
  421. SUB newRock (iRock)
  422.     DIM side AS LONG
  423.     RANDOMIZE TIMER * RND 'to avoid making twins
  424.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  425.     SELECT CASE side
  426.         CASE 1
  427.             r(iRock).x = -10
  428.             r(iRock).y = rrnd(20, ymax - 20)
  429.             r(iRock).heading = 3 * pi / 2 + RND * pi
  430.         CASE 2
  431.             r(iRock).x = xmax + 10
  432.             r(iRock).y = rrnd(20, ymax - 20)
  433.             r(iRock).heading = pi / 2 + RND * pi
  434.         CASE 3
  435.             r(iRock).x = rrnd(20, xmax - 20)
  436.             r(iRock).y = -10
  437.             r(iRock).heading = RND * pi
  438.         CASE 4
  439.             r(iRock).x = rrnd(20, xmax - 20)
  440.             r(iRock).y = ymax + 10
  441.             r(iRock).heading = pi + RND * pi
  442.     END SELECT
  443.     r(iRock).speed = rrnd(2, 5) 'speed, rotation angle, radius, gray coloring, spin, seed, hit for explosion
  444.     r(iRock).ra = RND * 2 * pi
  445.     r(iRock).r = irnd&(30, 100)
  446.     r(iRock).c = irnd&(10, 60)
  447.     r(iRock).spin = rrnd(-pi / 20, pi / 20)
  448.     r(iRock).seed = INT(RND * 64000) - 32000
  449.     r(iRock).explodeFrame = 0
  450.     r(iRock).live = 1
  451.  
  452. FUNCTION irnd& (n1, n2) 'return an integer between 2 numbers
  453.     DIM l%, h%
  454.     IF n1 > n2 THEN l% = n2: h% = n1 ELSE l% = n1: h% = n2
  455.     irnd& = INT(RND * (h% - l% + 1)) + l%
  456.  
  457. FUNCTION rrnd (n1, n2) ' return number (expecting reals =_single, double, _float depending on default / define setup)
  458.     rrnd = (n2 - n1) * RND + n1
  459.  
  460. SUB fellipse (CX AS LONG, CY AS LONG, a AS LONG, b AS LONG, C AS _UNSIGNED LONG)
  461.     ' CX = center x coordinate
  462.     ' CY = center y coordinate
  463.     '  a = semimajor axis
  464.     '  b = semiminor axis
  465.     '  C = fill color
  466.     IF a = 0 OR b = 0 THEN EXIT SUB
  467.     DIM h2 AS _INTEGER64
  468.     DIM w2 AS _INTEGER64
  469.     DIM h2w2 AS _INTEGER64
  470.     DIM x AS LONG
  471.     DIM y AS LONG
  472.     w2 = a * a
  473.     h2 = b * b
  474.     h2w2 = h2 * w2
  475.     LINE (CX - a, CY)-(CX + a, CY), C, BF
  476.     DO WHILE y < b
  477.         y = y + 1
  478.         x = SQR((h2w2 - y * y * w2) \ h2)
  479.         LINE (CX - x, CY + y)-(CX + x, CY + y), C, BF
  480.         LINE (CX - x, CY - y)-(CX + x, CY - y), C, BF
  481.     LOOP
  482.  
  483. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  484.     DIM D AS LONG
  485.     STATIC a&
  486.     D = _DEST
  487.     IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32)
  488.     _DEST a&
  489.     _DONTBLEND a& '  '<<<< new 2019-12-16 fix
  490.     PSET (0, 0), K
  491.     _BLEND a& '<<<< new 2019-12-16 fix
  492.     _DEST D
  493.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  494.  
  495. SUB fcirc (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG) 'vince version
  496.     DIM x0 AS LONG, y0 AS LONG, e AS LONG
  497.     x0 = R: y0 = 0: e = 0
  498.     DO WHILE y0 < x0
  499.         IF e <= 0 THEN
  500.             y0 = y0 + 1
  501.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  502.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  503.             e = e + 2 * y0
  504.         ELSE
  505.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  506.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  507.             x0 = x0 - 1: e = e - 2 * x0
  508.         END IF
  509.     LOOP
  510.     LINE (x - R, y)-(x + R, y), C, BF
  511.  
Title: Re: b+ Asteroids makeover
Post by: johnno56 on November 01, 2020, 01:29:32 am
Those last two versions are pretty cool. 'Explosions' were a nice touch... The introduction of the "alien" was a pure touch of deviousness! Space shooters. Ya gotta love 'em... Well done!!
Title: Re: b+ Asteroids makeover
Post by: bplus on November 01, 2020, 11:50:18 am
What more aliens, and moving through space (for 100% drawn animation)? sure we can do that :)
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 01, 2020, 03:15:40 pm
LOL awesome saucers! It's getting harder too. Is there a way to keep the game moving when the saucer blows up?
Title: Re: b+ Asteroids makeover
Post by: bplus on November 01, 2020, 05:05:32 pm
LOL awesome saucers! It's getting harder too. Is there a way to keep the game moving when the saucer blows up?

I am glad you like the saucers because more are coming your way! hee, hee wait until you see a couple of them double teaming you!

Yeah, as long as you have lives left ie <> 0 then press a button and play the next round. You might as well press the space bar because you don't want to stop shooting for a second! I have now increased lives at start to 10.

Bigger scores because target rich environment! Saucers or Death Bolders are 100 points.

M5 more of what you love in moving space (WIP):
Code: QB64: [Select]
  1. _TITLE "b+ Asteroids m5 They are Here" 'started 2018-07-13"
  2. ' 2020-10-27 remove the alternate subs and get down below 200 LOC almost there now! new shooter action font and background
  3. ' 2020-10-28 another makeover explosions and split asteroids
  4. ' 2020-10-29 fix baby rock management, break between lives
  5. ' 2020-10-29 fix left/right gun, fix explosions over many frames to eliminate pause in action, speed up 60 fps
  6. ' 2020-10-30 m3 SierraKen's idea to angle shooter with mousewheel also finish WASD options, more rocks, points system
  7. ' points:
  8. ' The higher the speed the better    speed range 2 to 5, diff = 3 * 33.3333 = 100          s - 2 * 33.3333
  9. ' The lower the color the better   color range 10 to 60, diff =      50 * 2 = 100  50 - (c - 10) * 2
  10. ' The small        er the size the better  size range 10 to 100, diff = 90 * 1.1111 = 100  90 - (sz -10) * 1.1111
  11. '        ((speed - 2) * 33.3333 + (50 - (c -10)) * 2 + (90 - (r - 10)) * 1.1111) / 3 = 100 best score per hit
  12. ' 2020-10-30 increase level of difficulty, fix double lives lost, add an ending after all lives spent.
  13. ' 2020-10-31 M4 They are Here - the aliens have accepted my invitaion for war games don't get caught in their beam.
  14. ' rework ending and variable LONG suffix. Aliens on the attack 100 points before or after transformed into the Bolder of Death.
  15. ' 2020-11-01 FX Moving through space, Oh yeah, more aliens!
  16.  
  17. '================================================================================================================
  18.  
  19. '    NOTE: !!!!!!!!!!!!!!!   When there is a pause in action, just hit any key to reset next life.
  20.  
  21. '================================================================================================================
  22.  
  23. CONST xmax = 1200, ymax = 700, pi = _PI, polyAngle = _PI / 6, nRocks = 300, nBullets = 2000, bSpeed = 15
  24.  
  25. TYPE alienType
  26.     x AS SINGLE
  27.     y AS SINGLE
  28.     dx AS SINGLE
  29.     dy AS SINGLE
  30.     ls AS LONG ' lights offset
  31.     c AS _UNSIGNED LONG ' color
  32.     live AS LONG
  33.     attackFrame AS LONG
  34.     fireX AS LONG
  35.     fireY AS LONG
  36.     transform AS LONG
  37.  
  38. TYPE particle
  39.     x AS LONG
  40.     y AS LONG
  41.     dx AS SINGLE
  42.     dy AS SINGLE
  43.     size AS SINGLE
  44.     kolor AS _UNSIGNED LONG
  45.  
  46. TYPE bullet
  47.     x AS LONG
  48.     y AS LONG
  49.     dx AS SINGLE
  50.     dy AS SINGLE
  51.     live AS LONG
  52.  
  53. TYPE shipType
  54.     x AS LONG
  55.     y AS LONG
  56.     live AS LONG
  57.     a AS SINGLE '   rotated position usu gun left or right (mouse button), maybe up press w or down press z
  58.  
  59. TYPE rock
  60.     x AS LONG
  61.     y AS LONG
  62.     r AS LONG '            radius
  63.     ra AS SINGLE '         rotation position   a = a + spin
  64.     heading AS SINGLE '    heading from which dx, dy are calc with speed
  65.     speed AS SINGLE '      speed
  66.     spin AS SINGLE '       rotation direction and amount
  67.     seed AS LONG '         for drawing rocks with RND USING
  68.     c AS LONG '            color   rgb(c, c, c)
  69.     live AS LONG '         need this to track rocks still active like bullets
  70.     explodeFrame AS LONG ' after a rock is hit by bullet, it explodes and in more than one frame
  71.  
  72. REDIM SHARED aliens(1 TO 5) AS alienType
  73. DIM SHARED dots(2000) AS particle
  74. DIM SHARED b(nBullets) AS bullet
  75. DIM SHARED ship AS shipType
  76. DIM SHARED r(nRocks) AS rock
  77. DIM SHARED points AS LONG
  78. 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
  79.  
  80. DIM fnt AS LONG, fnt2 AS LONG ' file LOAD handles
  81. DIM i AS LONG, bullets AS LONG, fire AS LONG ' index and bullets
  82. DIM r AS LONG, newRockN AS LONG, maxBabyRocks AS LONG, br AS LONG, hits AS LONG ' rock stuff
  83. DIM ai AS LONG, alienN AS LONG ' alien index and number
  84. DIM s$, t, lastt ' general string and times
  85.  
  86. SCREEN _NEWIMAGE(xmax, ymax, 32)
  87. _SCREENMOVE 100, 20
  88.  
  89. fnt = _LOADFONT("ARLRDBD.ttf", 16, "MONOSPACE")
  90. fnt2 = _LOADFONT("ARLRDBD.ttf", 40, "MONOSPACE")
  91. _FONT fnt
  92. COLOR &HFF00FFFF, &H00000000
  93.  
  94. alienN = 1
  95. rocks = 4 ' always active rocks
  96. lives = 10
  97. WHILE lives > 0 AND _KEYDOWN(27) = 0 ' init start restart
  98.     REDIM aliens(1 TO alienN) AS alienType
  99.     FOR ai = 1 TO alienN
  100.         newAlien ai
  101.     NEXT
  102.     FOR i = 1 TO nRocks 'reset rocks mainly clear baby rocks
  103.         newRock (i)
  104.         IF i > rocks THEN r(i).live = 0
  105.     NEXT
  106.     ship.x = xmax / 2 'avoids explosions top left corner at start, dang still get some!
  107.     ship.y = ymax / 2
  108.     ship.live = 1
  109.     WHILE ship.live AND _KEYDOWN(27) = 0
  110.         'draw everything then process bullets
  111.         drawStars 1
  112.         '   CIRCLE (aliens.fireX, aliens.fireY), 10, &HFFFFFFFF   transformtion poimt Bolder of Death
  113.         s$ = "Lives:" + STR$(lives) + "  Hits:" + STR$(hits) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits * 100 / bullets)) + "%"
  114.         _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 20), s$
  115.         _FONT fnt2
  116.         s$ = STR$(points)
  117.         _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  118.         _FONT fnt
  119.         FOR ai = 1 TO alienN
  120.             drawAliens ai
  121.         NEXT
  122.  
  123.         FOR i = 1 TO nRocks
  124.             IF r(i).live THEN drawRock i ' while drawing rocks the ship could be blown up
  125.         NEXT
  126.         FOR i = 1 TO nRocks 'smoke up the place with rock debris fields still flying out from hit frames ago
  127.             IF r(i).explodeFrame THEN
  128.                 r(i).explodeFrame = r(i).explodeFrame + 1
  129.                 IF r(i).explodeFrame > .5 * r(i).r THEN
  130.                     r(i).explodeFrame = 0
  131.                     IF i <= rocks THEN newRock i ' now replace the rock
  132.                 ELSE
  133.                     explode r(i).x, r(i).y, r(i).r, r(i).explodeFrame
  134.                 END IF
  135.             END IF
  136.         NEXT
  137.         IF ship.live THEN
  138.             FOR ai = 1 TO alienN
  139.                 IF SQR((aliens(ai).x - ship.x) ^ 2 + (aliens(ai).y - ship.y) ^ 2) < 60 THEN 'aliens and ship collisde boom boom
  140.                     FOR br = 1 TO 200
  141.                         fcirc ship.x, ship.y, br, _RGB32(255 - br, 255 - 2 * br, 0)
  142.                         _DISPLAY
  143.                         _LIMIT 300
  144.                     NEXT
  145.                     ship.live = 0
  146.                     _CONTINUE
  147.                 ELSE
  148.                     drawship
  149.                 END IF
  150.             NEXT
  151.             WHILE _MOUSEINPUT
  152.                 ship.a = ship.a + _MOUSEWHEEL * pi / 8 ' 22.5  degree changes, Thank Ken for this :)
  153.             WEND 'update ship
  154.             ship.x = _MOUSEX: ship.y = _MOUSEY
  155.             IF _MOUSEBUTTON(1) THEN ship.a = pi 'this is new left and right guns
  156.             IF _MOUSEBUTTON(2) THEN ship.a = 0
  157.             IF _KEYDOWN(ASC("w")) THEN ship.a = 1.5 * pi ' well it works but ??
  158.             IF _KEYDOWN(ASC("a")) THEN ship.a = pi
  159.             IF _KEYDOWN(ASC("s")) THEN ship.a = .5 * pi
  160.             IF _KEYDOWN(ASC("d")) THEN ship.a = 0
  161.             fire = 0
  162.             IF _KEYDOWN(32) THEN 'fire bullets
  163.                 t = TIMER(.01)
  164.                 IF lastt = 0 OR t - lastt > .2 THEN fire = 1: lastt = t
  165.             END IF
  166.             FOR i = 0 TO nBullets 'handle bullets
  167.                 IF b(i).live = 0 AND fire = 1 THEN 'have inactive bullet to use
  168.                     b(i).x = ship.x + bSpeed * COS(ship.a)
  169.                     b(i).y = ship.y + bSpeed * SIN(ship.a)
  170.                     b(i).dx = bSpeed * COS(ship.a)
  171.                     b(i).dy = bSpeed * SIN(ship.a)
  172.                     b(i).live = -1
  173.                     bullets = bullets + 1
  174.                     fire = 0
  175.                 END IF
  176.                 IF b(i).live THEN 'new location
  177.                     b(i).x = b(i).x + b(i).dx
  178.                     b(i).y = b(i).y + b(i).dy
  179.                     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
  180.  
  181.                         'bullet hit aliens?
  182.                         FOR ai = 1 TO alienN
  183.                             IF SQR((aliens(ai).x - b(i).x) ^ 2 + (aliens(ai).y - b(i).y) ^ 2) < 30 THEN
  184.                                 FOR br = 1 TO 120
  185.                                     CIRCLE (aliens(ai).x, aliens(ai).y), br / 3, plasma~&(0)
  186.                                 NEXT
  187.                                 _DISPLAY
  188.                                 _DELAY .05
  189.                                 aliens(ai).live = 0
  190.                                 newAlien ai
  191.                                 points = points + 100
  192.                                 b(i).live = 0
  193.                                 _CONTINUE
  194.                             END IF
  195.                         NEXT
  196.                         FOR r = 1 TO nRocks 'check for collision with rock
  197.                             IF r(r).live THEN
  198.                                 IF SQR((r(r).x - b(i).x) ^ 2 + (r(r).y - b(i).y) ^ 2) < r(r).r THEN 'its a hit!
  199.                                     r(r).explodeFrame = 1 'linger with explosion
  200.                                     r(r).live = 0
  201.                                     hits = hits + 1
  202.                                     points = points + ((r(r).speed - 2) * 33.3333 + (50 - (r(r).c - 10)) * 2 + (90 - (r(r).r - 10)) * 1.1111) / 3
  203.                                     IF r(r).r > 30 THEN '       split rock  into ? new ones
  204.                                         maxBabyRocks = INT((r(r).r - 10) / 10)
  205.                                         maxBabyRocks = irnd&(2, maxBabyRocks) ' pick a number of baby Rocks
  206.                                         FOR br = 1 TO maxBabyRocks
  207.                                             '                        new rock
  208.                                             newRockN = freeRock& '                          get inactive rock number
  209.                                             newRock newRockN '                              new identity and activate
  210.                                             r(newRockN).r = (r(r).r - 10) / maxBabyRocks '  split in equal parts minus 20% mass
  211.                                             r(newRockN).x = r(r).x + irnd&(-30, 30) '       thrown from parent
  212.                                             r(newRockN).y = r(r).y + irnd&(-30, 30)
  213.                                             r(newRockN).c = r(r).c '                   same color as parent
  214.                                             r(newRockN).heading = rrnd(ship.a - .75 * pi, ship.a + .75 * pi)
  215.                                         NEXT
  216.                                     END IF ' big enough to split
  217.                                     b(i).live = 0 'kill bullet
  218.                                 END IF ' hit rock
  219.                             END IF 'rock is there
  220.                         NEXT ' rock
  221.                         IF b(i).live THEN fcirc b(i).x, b(i).y, 3, _RGB32(255, 255, 0) 'draws bullet
  222.                     ELSE
  223.                         b(i).live = 0 'out of bounds
  224.                     END IF ' bullet is in bounds
  225.                 END IF ' bullet live
  226.             NEXT ' bullet
  227.         END IF ' if ship still live
  228.         _DISPLAY
  229.         IF ship.live = 0 THEN SLEEP ELSE _LIMIT 60 ' if ship dies let's rest and regroup  before restart next life
  230.     WEND
  231.     lives = lives - 1
  232.     IF lives MOD 4 = 0 THEN rocks = rocks + 1
  233.     IF lives MOD 4 = 2 THEN alienN = alienN + 1
  234. ship.x = -200: ship.y = -200 'get it out of the way
  235. i = 0
  236. WHILE _KEYDOWN(ASC("q")) = 0
  237.     drawStars 0
  238.     i = i + 1
  239.     IF i MOD 30 = 29 AND rocks < nRocks THEN rocks = rocks + 1: r(rocks).live = 1
  240.     FOR r = 1 TO nRocks
  241.         IF r(r).live THEN drawRock r
  242.     NEXT
  243.     s$ = "Lives:" + STR$(lives) + "  Hits:" + STR$(hits) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits * 100 / bullets)) + "%"
  244.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 20), s$
  245.     _FONT fnt2
  246.     s$ = STR$(points)
  247.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  248.     _FONT fnt
  249.     s$ = "Press q to quit"
  250.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 + 100), s$
  251.     _DISPLAY
  252.     _LIMIT 60
  253.  
  254. SUB drawStars (moving)
  255.     TYPE starType
  256.         x AS SINGLE
  257.         y AS SINGLE
  258.         size AS SINGLE
  259.         c AS INTEGER
  260.     END TYPE
  261.     STATIC beenHere, stars(600) AS starType, cy AS LONG
  262.     DIM i AS LONG
  263.     IF beenHere = 0 THEN 'static part
  264.         FOR i = 0 TO 200
  265.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = 0
  266.             stars(i).c = irnd&(80, 140)
  267.         NEXT
  268.         FOR i = 0 TO 200
  269.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = .3
  270.             stars(i).c = irnd&(80, 140)
  271.         NEXT
  272.  
  273.         FOR i = 1 TO 140
  274.             stars(i + 400).x = RND * xmax: stars(i + 400).y = RND * ymax: stars(i + 100).size = .6
  275.             stars(i).c = irnd&(110, 170)
  276.         NEXT
  277.         FOR i = 1 TO 50
  278.             stars(i + 540).x = RND * xmax: stars(i + 540).y = RND * ymax: stars(i + 170).size = 1.2
  279.             stars(i).c = irnd&(140, 200)
  280.         NEXT
  281.         FOR i = 1 TO 10
  282.             stars(i + 590).x = RND * xmax: stars(i + 590).y = RND * ymax: stars(i + 195).size = 2.4
  283.             stars(i).c = irnd&(170, 235)
  284.         NEXT
  285.         cy = ymax / 2
  286.         beenHere = 1
  287.     END IF
  288.     FOR i = 0 TO cy
  289.         LINE (0, i)-(xmax, i), _RGB32(0, 0, .1 * i + 4)
  290.         LINE (0, ymax - i)-(xmax, ymax - i), _RGB(0, 0, .1 * i + 4)
  291.     NEXT
  292.     FOR i = 0 TO 200
  293.         IF moving THEN
  294.             stars(i).x = stars(i).x + .2 * stars(i).size ^ stars(i).size
  295.             IF stars(i).x > xmax THEN stars(i).x = -1 * RND * 20
  296.         END IF
  297.         fcirc stars(i).x, stars(i).y, stars(i).size, _RGB32(stars(i).c - 10, stars(i).c, stars(i).c + 10)
  298.     NEXT
  299.  
  300. SUB newAlien (i AS LONG)
  301.     DIM side AS LONG, heading
  302.     RANDOMIZE TIMER * RND 'to avoid making twins
  303.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  304.     aliens(i).fireX = irnd(10, xmax - 10)
  305.     aliens(i).fireY = irnd(10, ymax - 10)
  306.      aliens(i).attackFrame = irnd(30, 400)    ' EDIT a tweak to survive a little long before murdered with low lives
  307.     SELECT CASE side
  308.         CASE 1
  309.             aliens(i).x = -10
  310.             aliens(i).y = rrnd(20, ymax - 20)
  311.         CASE 2
  312.             aliens(i).x = xmax + 10
  313.             aliens(i).y = rrnd(20, ymax - 20)
  314.         CASE 3
  315.             aliens(i).x = rrnd(20, xmax - 20)
  316.             aliens(i).y = -10
  317.         CASE 4
  318.             aliens(i).x = rrnd(20, xmax - 20)
  319.             aliens(i).y = ymax + 10
  320.     END SELECT
  321.     heading = _ATAN2(aliens(i).fireY - aliens(i).y, aliens(i).fireX - aliens(i).x)
  322.     aliens(i).dx = 3.5 * COS(heading)
  323.     aliens(i).dy = 3.5 * SIN(heading)
  324.     aliens(i).live = 0
  325.     aliens(i).transform = 0
  326.     aliens(i).c = _RGB32(irnd(128, 255), irnd(0, 255), irnd(0, 255))
  327.  
  328. FUNCTION plasma~& (new AS LONG)
  329.     STATIC r, g, b, cnt, beenHere
  330.     IF beenHere = 0 OR new THEN
  331.         r = RND: g = RND: b = RND: beenHere = 1: cnt = 0
  332.     END IF
  333.     cnt = cnt + .2
  334.     plasma~& = _RGB32(127 + 127 * SIN(r * cnt), 127 + 127 * SIN(g * cnt), 127 + 127 * SIN(b * cnt))
  335.  
  336. SUB drawAliens (i AS LONG) 'shipType
  337.     DIM light AS LONG, heading, r AS LONG, g AS LONG, b AS LONG
  338.     IF aliens(i).live THEN
  339.         IF aliens(i).transform = 0 THEN
  340.             r = _RED32(aliens(i).c): g = _GREEN32(aliens(i).c): b = _BLUE32(aliens(i).c)
  341.             fellipse aliens(i).x, aliens(i).y, 6, 15, _RGB32(r, g - 120, b - 100)
  342.             fellipse aliens(i).x, aliens(i).y, 18, 11, _RGB32(r, g - 60, b - 50)
  343.             fellipse aliens(i).x, aliens(i).y, 30, 7, _RGB32(r, g, b)
  344.             FOR light = 1 TO 12
  345.                 fcirc aliens(i).x - 35 + 5 * light + aliens(i).ls, aliens(i).y, 1, _RGB32(aliens(i).ls * 50, aliens(i).ls * 50, aliens(i).ls * 50)
  346.             NEXT
  347.             aliens(i).ls = aliens(i).ls + 1
  348.             IF aliens(i).ls > 5 THEN aliens(i).ls = 0
  349.         ELSE
  350.             fcirc aliens(i).x, aliens(i).y, 30, aliens(i).c
  351.         END IF
  352.         'time to shoot?
  353.         aliens(i).x = aliens(i).x + aliens(i).dx
  354.         aliens(i).y = aliens(i).y + aliens(i).dy
  355.         IF SQR((aliens(i).fireX - aliens(i).x) ^ 2 + (aliens(i).fireY - aliens(i).y) ^ 2) < 5 THEN 'transform into the bolder of death
  356.             aliens(i).transform = 1
  357.             heading = _ATAN2(ship.y - aliens(i).y, ship.x - aliens(i).x)
  358.             aliens(i).dx = 10 * COS(heading)
  359.             aliens(i).dy = 10 * SIN(heading)
  360.         END IF
  361.         IF aliens(i).x < -10 OR aliens(i).x > xmax + 10 THEN
  362.             IF aliens(i).y < -10 OR aliens(i).y > ymax + 10 THEN '  out of bounds goodbye bolder of death!
  363.                 aliens(i).live = 0 'man we dodged a bullet here!!!!
  364.                 newAlien i 'reset the trap
  365.             END IF
  366.         END IF
  367.     ELSE
  368.         IF aliens(i).attackFrame THEN
  369.             aliens(i).attackFrame = aliens(i).attackFrame - 1
  370.             IF aliens(i).attackFrame = 0 THEN
  371.                 aliens(i).live = 1
  372.             END IF
  373.         END IF
  374.     END IF
  375.  
  376. FUNCTION freeRock&
  377.     DIM i AS LONG
  378.     FOR i = rocks + 1 TO nRocks ' look for inactive rock number
  379.         IF r(i).live = 0 AND r(i).explodeFrame = 0 THEN freeRock& = i: EXIT FUNCTION
  380.     NEXT
  381.  
  382. SUB explode (x AS LONG, y AS LONG, r AS LONG, frm AS LONG)
  383.     DIM maxParticles AS LONG, i AS LONG, rounds AS LONG, loopCount AS LONG
  384.     maxParticles = r * 4
  385.     FOR i = 1 TO r
  386.         NewDot i, x, y, r
  387.     NEXT
  388.     rounds = r
  389.     FOR loopCount = 0 TO frm
  390.         IF _KEYDOWN(27) THEN END
  391.         FOR i = 1 TO rounds
  392.             dots(i).x = dots(i).x + dots(i).dx
  393.             dots(i).y = dots(i).y + dots(i).dy
  394.             fcirc dots(i).x, dots(i).y, dots(i).size, dots(i).kolor
  395.         NEXT
  396.         IF rounds < maxParticles THEN
  397.             FOR i = 1 TO r
  398.                 NewDot (rounds + i), x, y, r
  399.             NEXT
  400.             rounds = rounds + r
  401.         END IF
  402.     NEXT
  403.  
  404. SUB NewDot (i AS LONG, x AS LONG, y AS LONG, r AS LONG)
  405.     DIM angle, rd
  406.     angle = pi * 2 * RND
  407.     rd = RND * 30
  408.     dots(i).x = x + rd * COS(angle)
  409.     dots(i).y = y + rd * SIN(angle)
  410.     dots(i).size = RND * r * .05
  411.     rd = RND 'STxAxTIC recommended for rounder spreads
  412.     dots(i).dx = rd * 10 * (10 - 2 * dots(i).size) * COS(angle)
  413.     dots(i).dy = rd * 10 * (10 - 2 * dots(i).size) * SIN(angle)
  414.     rd = 20 + RND * 70
  415.     dots(i).kolor = _RGBA32(rd, rd, rd, 80)
  416.  
  417. SUB drawship 'simple red iso triangle pointed towards radianAngle
  418.     DIM x1 AS LONG, y1 AS LONG, x2 AS LONG, y2 AS LONG, x3 AS LONG, y3 AS LONG
  419.     'calculate 3 tail points of triangle ship
  420.     x1 = ship.x + 40 * COS(ship.a - pi) '   middle
  421.     y1 = ship.y + 40 * SIN(ship.a - pi) '
  422.     x2 = ship.x + 60 * COS(ship.a + .9 * pi) ' wing
  423.     y2 = ship.y + 60 * SIN(ship.a + .9 * pi)
  424.     x3 = ship.x + 60 * COS(ship.a - .9 * pi) ' other wing
  425.     y3 = ship.y + 60 * SIN(ship.a - .9 * pi)
  426.     ftri ship.x, ship.y, x1, y1, x2, y2, _RGB32(80, 120, 80, 80)
  427.     ftri ship.x, ship.y, x1, y1, x3, y3, _RGB32(60, 100, 60, 80)
  428.     LINE (ship.x, ship.y)-(x1, y1), _RGB32(255, 255, 128)
  429.     LINE (ship.x, ship.y)-(x2, y2), _RGB32(180, 180, 120)
  430.     LINE (ship.x, ship.y)-(x3, y3), _RGB32(180, 180, 120)
  431.  
  432. SUB drawRock (iRock)
  433.     RANDOMIZE USING r(iRock).seed 'this prevents having to save a particular sequence of random number
  434.     DIM dx, dy, rad AS LONG, 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
  435.     DIM x2 AS LONG, y2 AS LONG
  436.     dx = r(iRock).speed * COS(r(iRock).heading)
  437.     dy = r(iRock).speed * SIN(r(iRock).heading) 'update location
  438.     r(iRock).ra = r(iRock).ra + r(iRock).spin
  439.     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
  440.         IF iRock <= rocks THEN newRock iRock ELSE r(iRock).live = 0
  441.         EXIT SUB ' reassigned get out of here
  442.     ELSE
  443.         r(iRock).x = r(iRock).x + dx
  444.         r(iRock).y = r(iRock).y + dy
  445.     END IF
  446.     IF ((r(iRock).x - ship.x) ^ 2 + (r(iRock).y - ship.y) ^ 2) ^ .5 < r(iRock).r + 30 THEN 'rock collides with ship?
  447.         FOR rad = 1 TO 200
  448.             fcirc ship.x, ship.y, rad, _RGB32(255 - rad, 255 - 2 * rad, 0)
  449.             _DISPLAY
  450.             _LIMIT 300
  451.         NEXT
  452.         ship.live = 0
  453.         IF iRock <= rocks THEN newRock iRock ELSE r(iRock).live = 0
  454.         EXIT SUB
  455.     END IF
  456.     FOR j = 10 TO 3 STEP -1 '                  rock drawing (see demo program where developed code)
  457.         rRad = .1 * j * r(iRock).r
  458.         leg = rRad * (RND * .7 + .3)
  459.         x0 = r(iRock).x + leg * COS(r(iRock).ra)
  460.         y0 = r(iRock).y + leg * SIN(r(iRock).ra)
  461.         rc = r(iRock).c + 30 * RND - 15
  462.         c~& = _RGB32(rc + 5, rc - 10, rc + 5)
  463.         x1 = x0
  464.         y1 = y0
  465.         xoff = RND * 20 - 10 + r(iRock).x
  466.         yoff = RND * 20 - 10 + r(iRock).y
  467.         FOR i = 1 TO 12
  468.             leg = rRad * (RND * .35 + .65)
  469.             IF i = 12 THEN
  470.                 x2 = x0: y2 = y0
  471.             ELSE
  472.                 x2 = xoff + leg * COS(i * polyAngle + r(iRock).ra)
  473.                 y2 = yoff + leg * SIN(i * polyAngle + r(iRock).ra)
  474.             END IF
  475.             ftri r(iRock).x, r(iRock).y, x1, y1, x2, y2, c~&
  476.             x1 = x2: y1 = y2
  477.         NEXT
  478.     NEXT
  479.  
  480. SUB newRock (iRock)
  481.     DIM side AS LONG
  482.     RANDOMIZE TIMER * RND 'to avoid making twins
  483.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  484.     SELECT CASE side
  485.         CASE 1
  486.             r(iRock).x = -10
  487.             r(iRock).y = rrnd(20, ymax - 20)
  488.             r(iRock).heading = 3 * pi / 2 + RND * pi
  489.         CASE 2
  490.             r(iRock).x = xmax + 10
  491.             r(iRock).y = rrnd(20, ymax - 20)
  492.             r(iRock).heading = pi / 2 + RND * pi
  493.         CASE 3
  494.             r(iRock).x = rrnd(20, xmax - 20)
  495.             r(iRock).y = -10
  496.             r(iRock).heading = RND * pi
  497.         CASE 4
  498.             r(iRock).x = rrnd(20, xmax - 20)
  499.             r(iRock).y = ymax + 10
  500.             r(iRock).heading = pi + RND * pi
  501.     END SELECT
  502.     r(iRock).speed = rrnd(2, 5) 'speed, rotation angle, radius, gray coloring, spin, seed, hit for explosion
  503.     r(iRock).ra = RND * 2 * pi
  504.     r(iRock).r = irnd&(30, 100)
  505.     r(iRock).c = irnd&(10, 60)
  506.     r(iRock).spin = rrnd(-pi / 20, pi / 20)
  507.     r(iRock).seed = INT(RND * 64000) - 32000
  508.     r(iRock).explodeFrame = 0
  509.     r(iRock).live = 1
  510.  
  511. FUNCTION irnd& (n1, n2) 'return an integer between 2 numbers
  512.     DIM l%, h%
  513.     IF n1 > n2 THEN l% = n2: h% = n1 ELSE l% = n1: h% = n2
  514.     irnd& = INT(RND * (h% - l% + 1)) + l%
  515.  
  516. FUNCTION rrnd (n1, n2) ' return number (expecting reals =_single, double, _float depending on default / define setup)
  517.     rrnd = (n2 - n1) * RND + n1
  518.  
  519. SUB fellipse (CX AS LONG, CY AS LONG, xr AS LONG, yr AS LONG, C AS _UNSIGNED LONG)
  520.     IF xr = 0 OR yr = 0 THEN EXIT SUB
  521.     DIM x AS LONG, y AS LONG
  522.     w2 = xr * xr: h2 = yr * yr: h2w2 = h2 * w2
  523.     LINE (CX - xr, CY)-(CX + xr, CY), C, BF
  524.     DO WHILE y < yr
  525.         y = y + 1
  526.         x = SQR((h2w2 - y * y * w2) \ h2)
  527.         LINE (CX - x, CY + y)-(CX + x, CY + y), C, BF
  528.         LINE (CX - x, CY - y)-(CX + x, CY - y), C, BF
  529.     LOOP
  530.  
  531. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  532.     DIM D AS LONG
  533.     STATIC a&
  534.     D = _DEST
  535.     IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32)
  536.     _DEST a&
  537.     _DONTBLEND a& '  '<<<< new 2019-12-16 fix
  538.     PSET (0, 0), K
  539.     _BLEND a& '<<<< new 2019-12-16 fix
  540.     _DEST D
  541.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  542.  
  543. SUB fcirc (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG) 'vince version
  544.     DIM x0 AS LONG, y0 AS LONG, e AS LONG
  545.     x0 = R: y0 = 0: e = 0
  546.     DO WHILE y0 < x0
  547.         IF e <= 0 THEN
  548.             y0 = y0 + 1
  549.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  550.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  551.             e = e + 2 * y0
  552.         ELSE
  553.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  554.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  555.             x0 = x0 - 1: e = e - 2 * x0
  556.         END IF
  557.     LOOP
  558.     LINE (x - R, y)-(x + R, y), C, BF
  559.  

You just need the font from the asset file now,
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 01, 2020, 05:53:18 pm
LOL Great job!!!! I'll put this in my Games folder on my computer. :) Thanks for making it.
Title: Re: b+ Asteroids makeover
Post by: bplus on November 01, 2020, 05:59:45 pm
LOL Great job!!!! I'll put this in my Games folder on my computer. :) Thanks for making it.

A little tweak to live longer:
Code: QB64: [Select]
  1. aliens(i).attackFrame = irnd(30, 400)    ' EDIT a tweak to survive a little long before getting murdered with low lives over and over...

Already edited in code above.
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 01, 2020, 07:45:21 pm
Thanks.
Title: Re: b+ Asteroids makeover
Post by: bplus on November 01, 2020, 09:04:03 pm
M6 Play again option, continuous shoot (save the spacebar!), save High Score:
Code: QB64: [Select]
  1. _TITLE "b+ Asteroids m6 Play Again" 'started 2018-07-13"
  2. ' 2020-10-27 remove the alternate subs and get down below 200 LOC almost there now! new shooter action font and background
  3. ' 2020-10-28 another makeover explosions and split asteroids
  4. ' 2020-10-29 fix baby rock management, break between lives
  5. ' 2020-10-29 fix left/right gun, fix explosions over many frames to eliminate pause in action, speed up 60 fps
  6. ' 2020-10-30 m3 SierraKen's idea to angle shooter with mousewheel also finish WASD options, more rocks, points system
  7. ' points:
  8. ' The higher the speed the better    speed range 2 to 5, diff = 3 * 33.3333 = 100          s - 2 * 33.3333
  9. ' The lower the color the better   color range 10 to 60, diff =      50 * 2 = 100  50 - (c - 10) * 2
  10. ' The small        er the size the better  size range 10 to 100, diff = 90 * 1.1111 = 100  90 - (sz -10) * 1.1111
  11. '        ((speed - 2) * 33.3333 + (50 - (c -10)) * 2 + (90 - (r - 10)) * 1.1111) / 3 = 100 best score per hit
  12. ' 2020-10-30 increase level of difficulty, fix double lives lost, add an ending after all lives spent.
  13. ' 2020-10-31 M4 They are Here - the aliens have accepted my invitaion for war games don't get caught in their beam.
  14. ' rework ending and variable LONG suffix. Aliens on the attack 100 points before or after transformed into the Bolder of Death.
  15. ' 2020-11-01 M5 FX Moving through space, Oh yeah, more aliens!
  16. ' 2020-11-01 M6 add play again and save high game , continuous shoot
  17.  
  18. '================================================================================================================
  19.  
  20. '    NOTE: !!!!!!!!!!!!!!!   When there is a pause in action, just hit any key to reset next life.
  21.  
  22. '================================================================================================================
  23.  
  24. CONST xmax = 1200, ymax = 700, pi = _PI, polyAngle = _PI / 6, nRocks = 300, nBullets = 2000, bSpeed = 15
  25.  
  26. TYPE alienType
  27.     x AS SINGLE
  28.     y AS SINGLE
  29.     dx AS SINGLE
  30.     dy AS SINGLE
  31.     ls AS LONG ' lights offset
  32.     c AS _UNSIGNED LONG ' color
  33.     live AS LONG
  34.     attackFrame AS LONG
  35.     fireX AS LONG
  36.     fireY AS LONG
  37.     transform AS LONG
  38.  
  39. TYPE particle
  40.     x AS LONG
  41.     y AS LONG
  42.     dx AS SINGLE
  43.     dy AS SINGLE
  44.     size AS SINGLE
  45.     kolor AS _UNSIGNED LONG
  46.  
  47. TYPE bullet
  48.     x AS LONG
  49.     y AS LONG
  50.     dx AS SINGLE
  51.     dy AS SINGLE
  52.     live AS LONG
  53.  
  54. TYPE shipType
  55.     x AS LONG
  56.     y AS LONG
  57.     live AS LONG
  58.     a AS SINGLE '   rotated position usu gun left or right (mouse button), maybe up press w or down press z
  59.  
  60. TYPE rock
  61.     x AS LONG
  62.     y AS LONG
  63.     r AS LONG '            radius
  64.     ra AS SINGLE '         rotation position   a = a + spin
  65.     heading AS SINGLE '    heading from which dx, dy are calc with speed
  66.     speed AS SINGLE '      speed
  67.     spin AS SINGLE '       rotation direction and amount
  68.     seed AS LONG '         for drawing rocks with RND USING
  69.     c AS LONG '            color   rgb(c, c, c)
  70.     live AS LONG '         need this to track rocks still active like bullets
  71.     explodeFrame AS LONG ' after a rock is hit by bullet, it explodes and in more than one frame
  72.  
  73. REDIM SHARED aliens(1 TO 5) AS alienType
  74. DIM SHARED dots(2000) AS particle
  75. DIM SHARED b(nBullets) AS bullet
  76. DIM SHARED ship AS shipType
  77. DIM SHARED r(nRocks) AS rock
  78. DIM SHARED points AS LONG
  79. 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
  80.  
  81. DIM HS AS LONG, fnt AS LONG, fnt2 AS LONG ' file LOAD handles
  82. DIM i AS LONG, bullets AS LONG, fire AS LONG ' index and bullets
  83. DIM r AS LONG, newRockN AS LONG, maxBabyRocks AS LONG, br AS LONG, hits AS LONG ' rock stuff
  84. DIM ai AS LONG, alienN AS LONG ' alien index and number
  85. DIM hs$, s$, t, lastt ' general string and times
  86.  
  87. SCREEN _NEWIMAGE(xmax, ymax, 32)
  88. _SCREENMOVE 100, 20
  89.  
  90. fnt = _LOADFONT("ARLRDBD.ttf", 16, "MONOSPACE")
  91. fnt2 = _LOADFONT("ARLRDBD.ttf", 40, "MONOSPACE")
  92. _FONT fnt
  93. COLOR &HFF00FFFF, &H00000000
  94.  
  95. restart:
  96. IF _FILEEXISTS("Asteroids High Score.txt") THEN
  97.     OPEN "Asteroids High Score.txt" FOR INPUT AS #1
  98.     INPUT #1, HS
  99.     CLOSE #1
  100. hs$ = "  High Score:" + STR$(HS)
  101. lives = 10: alienN = 1: rocks = 4: ' always active rocks
  102. points = 0: hits = 0: bullets = 0
  103. WHILE lives > 0 AND _KEYDOWN(27) = 0 ' init start restart
  104.     REDIM aliens(1 TO alienN) AS alienType
  105.     FOR ai = 1 TO alienN
  106.         newAlien ai
  107.     NEXT
  108.     FOR i = 1 TO nRocks 'reset rocks mainly clear baby rocks
  109.         newRock (i)
  110.         IF i > rocks THEN r(i).live = 0
  111.     NEXT
  112.     ship.x = xmax / 2 'avoids explosions top left corner at start, dang still get some!
  113.     ship.y = ymax / 2
  114.     ship.live = 1
  115.     WHILE ship.live AND _KEYDOWN(27) = 0
  116.         'draw everything then process bullets
  117.         drawStars 1
  118.         '   CIRCLE (aliens.fireX, aliens.fireY), 10, &HFFFFFFFF   transformtion poimt Bolder of Death
  119.         s$ = "Lives:" + STR$(lives) + "  Hits:" + STR$(hits) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits * 100 / bullets)) + "%"
  120.         _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 20), s$
  121.         _FONT fnt2
  122.         s$ = STR$(points) + hs$
  123.         _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  124.         _FONT fnt
  125.         FOR ai = 1 TO alienN
  126.             drawAliens ai
  127.         NEXT
  128.  
  129.         FOR i = 1 TO nRocks
  130.             IF r(i).live THEN drawRock i ' while drawing rocks the ship could be blown up
  131.         NEXT
  132.         FOR i = 1 TO nRocks 'smoke up the place with rock debris fields still flying out from hit frames ago
  133.             IF r(i).explodeFrame THEN
  134.                 r(i).explodeFrame = r(i).explodeFrame + 1
  135.                 IF r(i).explodeFrame > .5 * r(i).r THEN
  136.                     r(i).explodeFrame = 0
  137.                     IF i <= rocks THEN newRock i ' now replace the rock
  138.                 ELSE
  139.                     explode r(i).x, r(i).y, r(i).r, r(i).explodeFrame
  140.                 END IF
  141.             END IF
  142.         NEXT
  143.         IF ship.live THEN
  144.             FOR ai = 1 TO alienN
  145.                 IF SQR((aliens(ai).x - ship.x) ^ 2 + (aliens(ai).y - ship.y) ^ 2) < 60 THEN 'aliens and ship collisde boom boom
  146.                     FOR br = 1 TO 200
  147.                         fcirc ship.x, ship.y, br, _RGB32(255 - br, 255 - 2 * br, 0)
  148.                         _DISPLAY
  149.                         _LIMIT 300
  150.                     NEXT
  151.                     ship.live = 0
  152.                     _CONTINUE
  153.                 ELSE
  154.                     drawship
  155.                 END IF
  156.             NEXT
  157.             WHILE _MOUSEINPUT
  158.                 ship.a = ship.a + _MOUSEWHEEL * pi / 8 ' 22.5  degree changes, Thank Ken for this :)
  159.             WEND 'update ship
  160.             ship.x = _MOUSEX: ship.y = _MOUSEY
  161.             IF _MOUSEBUTTON(1) THEN ship.a = pi 'this is new left and right guns
  162.             IF _MOUSEBUTTON(2) THEN ship.a = 0
  163.             IF _KEYDOWN(ASC("w")) THEN ship.a = 1.5 * pi ' well it works but ??
  164.             IF _KEYDOWN(ASC("a")) THEN ship.a = pi
  165.             IF _KEYDOWN(ASC("s")) THEN ship.a = .5 * pi
  166.             IF _KEYDOWN(ASC("d")) THEN ship.a = 0
  167.             fire = 0
  168.             'IF _KEYDOWN(32) THEN 'fire bullets
  169.             t = TIMER(.01)
  170.             IF lastt = 0 OR t - lastt > .2 THEN fire = 1: lastt = t
  171.             'END IF
  172.             FOR i = 0 TO nBullets 'handle bullets
  173.                 IF b(i).live = 0 AND fire = 1 THEN 'have inactive bullet to use
  174.                     b(i).x = ship.x + bSpeed * COS(ship.a)
  175.                     b(i).y = ship.y + bSpeed * SIN(ship.a)
  176.                     b(i).dx = bSpeed * COS(ship.a)
  177.                     b(i).dy = bSpeed * SIN(ship.a)
  178.                     b(i).live = -1
  179.                     bullets = bullets + 1
  180.                     fire = 0
  181.                 END IF
  182.                 IF b(i).live THEN 'new location
  183.                     b(i).x = b(i).x + b(i).dx
  184.                     b(i).y = b(i).y + b(i).dy
  185.                     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
  186.  
  187.                         'bullet hit aliens?
  188.                         FOR ai = 1 TO alienN
  189.                             IF SQR((aliens(ai).x - b(i).x) ^ 2 + (aliens(ai).y - b(i).y) ^ 2) < 30 THEN
  190.                                 FOR br = 1 TO 120
  191.                                     CIRCLE (aliens(ai).x, aliens(ai).y), br / 3, plasma~&(0)
  192.                                 NEXT
  193.                                 _DISPLAY
  194.                                 _DELAY .05
  195.                                 aliens(ai).live = 0
  196.                                 newAlien ai
  197.                                 points = points + 100
  198.                                 b(i).live = 0
  199.                                 _CONTINUE
  200.                             END IF
  201.                         NEXT
  202.                         FOR r = 1 TO nRocks 'check for collision with rock
  203.                             IF r(r).live THEN
  204.                                 IF SQR((r(r).x - b(i).x) ^ 2 + (r(r).y - b(i).y) ^ 2) < r(r).r THEN 'its a hit!
  205.                                     r(r).explodeFrame = 1 'linger with explosion
  206.                                     r(r).live = 0
  207.                                     hits = hits + 1
  208.                                     points = points + ((r(r).speed - 2) * 33.3333 + (50 - (r(r).c - 10)) * 2 + (90 - (r(r).r - 10)) * 1.1111) / 3
  209.                                     IF r(r).r > 30 THEN '       split rock  into ? new ones
  210.                                         maxBabyRocks = INT((r(r).r - 10) / 10)
  211.                                         maxBabyRocks = irnd&(2, maxBabyRocks) ' pick a number of baby Rocks
  212.                                         FOR br = 1 TO maxBabyRocks
  213.                                             '                        new rock
  214.                                             newRockN = freeRock& '                          get inactive rock number
  215.                                             newRock newRockN '                              new identity and activate
  216.                                             r(newRockN).r = (r(r).r - 10) / maxBabyRocks '  split in equal parts minus 20% mass
  217.                                             r(newRockN).x = r(r).x + irnd&(-30, 30) '       thrown from parent
  218.                                             r(newRockN).y = r(r).y + irnd&(-30, 30)
  219.                                             r(newRockN).c = r(r).c '                   same color as parent
  220.                                             r(newRockN).heading = rrnd(ship.a - .75 * pi, ship.a + .75 * pi)
  221.                                         NEXT
  222.                                     END IF ' big enough to split
  223.                                     b(i).live = 0 'kill bullet
  224.                                 END IF ' hit rock
  225.                             END IF 'rock is there
  226.                         NEXT ' rock
  227.                         IF b(i).live THEN fcirc b(i).x, b(i).y, 3, _RGB32(255, 255, 0) 'draws bullet
  228.                     ELSE
  229.                         b(i).live = 0 'out of bounds
  230.                     END IF ' bullet is in bounds
  231.                 END IF ' bullet live
  232.             NEXT ' bullet
  233.         END IF ' if ship still live
  234.         _DISPLAY
  235.         IF ship.live = 0 THEN SLEEP ELSE _LIMIT 60 ' if ship dies let's rest and regroup  before restart next life
  236.     WEND
  237.     lives = lives - 1
  238.     IF lives MOD 4 = 0 THEN rocks = rocks + 1
  239.     IF lives MOD 4 = 2 THEN alienN = alienN + 1
  240. IF points > HS THEN
  241.     OPEN "Asteroids High Score.txt" FOR OUTPUT AS #1
  242.     PRINT #1, points
  243.     CLOSE #1
  244. ship.x = -200: ship.y = -200 'get it out of the way
  245. i = 0
  246. DIM k$
  247. WHILE _KEYDOWN(ASC("q")) = 0
  248.     drawStars 0
  249.     i = i + 1
  250.     IF i MOD 30 = 29 AND rocks < nRocks THEN rocks = rocks + 1: r(rocks).live = 1
  251.     FOR r = 1 TO nRocks
  252.         IF r(r).live THEN drawRock r
  253.     NEXT
  254.     s$ = "Lives:" + STR$(lives) + "  Hits:" + STR$(hits) + "  Bullets:" + STR$(bullets) + "  Shooting:" + STR$(INT(hits * 100 / bullets)) + "%"
  255.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 - 20), s$
  256.     _FONT fnt2
  257.     s$ = STR$(points)
  258.     IF points > HS THEN s$ = s$ + " a New Record!" ELSE s$ = STR$(points) + hs$
  259.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2), s$
  260.     _FONT fnt
  261.     s$ = "Press q to quit, p or a to Play Again..."
  262.     _PRINTSTRING ((_WIDTH - _PRINTWIDTH(s$)) / 2, ymax / 2 + 100), s$
  263.     IF _KEYDOWN(ASC("a")) OR _KEYDOWN(ASC("p")) THEN GOTO restart
  264.     _DISPLAY
  265.     _LIMIT 60
  266.  
  267. SUB drawStars (moving)
  268.     TYPE starType
  269.         x AS SINGLE
  270.         y AS SINGLE
  271.         size AS SINGLE
  272.         c AS INTEGER
  273.     END TYPE
  274.     STATIC beenHere, stars(600) AS starType, cy AS LONG
  275.     DIM i AS LONG
  276.     IF beenHere = 0 THEN 'static part
  277.         FOR i = 0 TO 200
  278.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = 0
  279.             stars(i).c = irnd&(80, 140)
  280.         NEXT
  281.         FOR i = 0 TO 200
  282.             stars(i).x = RND * xmax: stars(i).y = RND * ymax: stars(i).size = .3
  283.             stars(i).c = irnd&(80, 140)
  284.         NEXT
  285.  
  286.         FOR i = 1 TO 140
  287.             stars(i + 400).x = RND * xmax: stars(i + 400).y = RND * ymax: stars(i + 100).size = .6
  288.             stars(i).c = irnd&(110, 170)
  289.         NEXT
  290.         FOR i = 1 TO 50
  291.             stars(i + 540).x = RND * xmax: stars(i + 540).y = RND * ymax: stars(i + 170).size = 1.2
  292.             stars(i).c = irnd&(140, 200)
  293.         NEXT
  294.         FOR i = 1 TO 10
  295.             stars(i + 590).x = RND * xmax: stars(i + 590).y = RND * ymax: stars(i + 195).size = 2.4
  296.             stars(i).c = irnd&(170, 235)
  297.         NEXT
  298.         cy = ymax / 2
  299.         beenHere = 1
  300.     END IF
  301.     FOR i = 0 TO cy
  302.         LINE (0, i)-(xmax, i), _RGB32(0, 0, .1 * i + 4)
  303.         LINE (0, ymax - i)-(xmax, ymax - i), _RGB(0, 0, .1 * i + 4)
  304.     NEXT
  305.     FOR i = 0 TO 200
  306.         IF moving THEN
  307.             stars(i).x = stars(i).x + .2 * stars(i).size ^ stars(i).size
  308.             IF stars(i).x > xmax THEN stars(i).x = -1 * RND * 20
  309.         END IF
  310.         fcirc stars(i).x, stars(i).y, stars(i).size, _RGB32(stars(i).c - 10, stars(i).c, stars(i).c + 10)
  311.     NEXT
  312.  
  313. SUB newAlien (i AS LONG)
  314.     DIM side AS LONG, heading
  315.     RANDOMIZE TIMER * RND 'to avoid making twins
  316.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  317.     aliens(i).fireX = irnd(10, xmax - 10)
  318.     aliens(i).fireY = irnd(10, ymax - 10)
  319.     aliens(i).attackFrame = irnd(30, 400) ' EDIT a tweak to survive a little long before getting murdered with low lives over and over...
  320.     SELECT CASE side
  321.         CASE 1
  322.             aliens(i).x = -10
  323.             aliens(i).y = rrnd(20, ymax - 20)
  324.         CASE 2
  325.             aliens(i).x = xmax + 10
  326.             aliens(i).y = rrnd(20, ymax - 20)
  327.         CASE 3
  328.             aliens(i).x = rrnd(20, xmax - 20)
  329.             aliens(i).y = -10
  330.         CASE 4
  331.             aliens(i).x = rrnd(20, xmax - 20)
  332.             aliens(i).y = ymax + 10
  333.     END SELECT
  334.     heading = _ATAN2(aliens(i).fireY - aliens(i).y, aliens(i).fireX - aliens(i).x)
  335.     aliens(i).dx = 3.5 * COS(heading)
  336.     aliens(i).dy = 3.5 * SIN(heading)
  337.     aliens(i).live = 0
  338.     aliens(i).transform = 0
  339.     aliens(i).c = _RGB32(irnd(128, 255), irnd(0, 255), irnd(0, 255))
  340.  
  341. FUNCTION plasma~& (new AS LONG)
  342.     STATIC r, g, b, cnt, beenHere
  343.     IF beenHere = 0 OR new THEN
  344.         r = RND: g = RND: b = RND: beenHere = 1: cnt = 0
  345.     END IF
  346.     cnt = cnt + .2
  347.     plasma~& = _RGB32(127 + 127 * SIN(r * cnt), 127 + 127 * SIN(g * cnt), 127 + 127 * SIN(b * cnt))
  348.  
  349. SUB drawAliens (i AS LONG) 'shipType
  350.     DIM light AS LONG, heading, r AS LONG, g AS LONG, b AS LONG
  351.     IF aliens(i).live THEN
  352.         IF aliens(i).transform = 0 THEN
  353.             r = _RED32(aliens(i).c): g = _GREEN32(aliens(i).c): b = _BLUE32(aliens(i).c)
  354.             fellipse aliens(i).x, aliens(i).y, 6, 15, _RGB32(r, g - 120, b - 100)
  355.             fellipse aliens(i).x, aliens(i).y, 18, 11, _RGB32(r, g - 60, b - 50)
  356.             fellipse aliens(i).x, aliens(i).y, 30, 7, _RGB32(r, g, b)
  357.             FOR light = 1 TO 12
  358.                 fcirc aliens(i).x - 35 + 5 * light + aliens(i).ls, aliens(i).y, 1, _RGB32(aliens(i).ls * 50, aliens(i).ls * 50, aliens(i).ls * 50)
  359.             NEXT
  360.             aliens(i).ls = aliens(i).ls + 1
  361.             IF aliens(i).ls > 5 THEN aliens(i).ls = 0
  362.         ELSE
  363.             fcirc aliens(i).x, aliens(i).y, 30, aliens(i).c
  364.         END IF
  365.         'time to shoot?
  366.         aliens(i).x = aliens(i).x + aliens(i).dx
  367.         aliens(i).y = aliens(i).y + aliens(i).dy
  368.         IF SQR((aliens(i).fireX - aliens(i).x) ^ 2 + (aliens(i).fireY - aliens(i).y) ^ 2) < 5 THEN 'transform into the bolder of death
  369.             aliens(i).transform = 1
  370.             heading = _ATAN2(ship.y - aliens(i).y, ship.x - aliens(i).x)
  371.             aliens(i).dx = 10 * COS(heading)
  372.             aliens(i).dy = 10 * SIN(heading)
  373.         END IF
  374.         IF aliens(i).x < -10 OR aliens(i).x > xmax + 10 THEN
  375.             IF aliens(i).y < -10 OR aliens(i).y > ymax + 10 THEN '  out of bounds goodbye bolder of death!
  376.                 aliens(i).live = 0 'man we dodged a bullet here!!!!
  377.                 newAlien i 'reset the trap
  378.             END IF
  379.         END IF
  380.     ELSE
  381.         IF aliens(i).attackFrame THEN
  382.             aliens(i).attackFrame = aliens(i).attackFrame - 1
  383.             IF aliens(i).attackFrame = 0 THEN
  384.                 aliens(i).live = 1
  385.             END IF
  386.         END IF
  387.     END IF
  388.  
  389. FUNCTION freeRock&
  390.     DIM i AS LONG
  391.     FOR i = rocks + 1 TO nRocks ' look for inactive rock number
  392.         IF r(i).live = 0 AND r(i).explodeFrame = 0 THEN freeRock& = i: EXIT FUNCTION
  393.     NEXT
  394.  
  395. SUB explode (x AS LONG, y AS LONG, r AS LONG, frm AS LONG)
  396.     DIM maxParticles AS LONG, i AS LONG, rounds AS LONG, loopCount AS LONG
  397.     maxParticles = r * 4
  398.     FOR i = 1 TO r
  399.         NewDot i, x, y, r
  400.     NEXT
  401.     rounds = r
  402.     FOR loopCount = 0 TO frm
  403.         IF _KEYDOWN(27) THEN END
  404.         FOR i = 1 TO rounds
  405.             dots(i).x = dots(i).x + dots(i).dx
  406.             dots(i).y = dots(i).y + dots(i).dy
  407.             fcirc dots(i).x, dots(i).y, dots(i).size, dots(i).kolor
  408.         NEXT
  409.         IF rounds < maxParticles THEN
  410.             FOR i = 1 TO r
  411.                 NewDot (rounds + i), x, y, r
  412.             NEXT
  413.             rounds = rounds + r
  414.         END IF
  415.     NEXT
  416.  
  417. SUB NewDot (i AS LONG, x AS LONG, y AS LONG, r AS LONG)
  418.     DIM angle, rd
  419.     angle = pi * 2 * RND
  420.     rd = RND * 30
  421.     dots(i).x = x + rd * COS(angle)
  422.     dots(i).y = y + rd * SIN(angle)
  423.     dots(i).size = RND * r * .05
  424.     rd = RND 'STxAxTIC recommended for rounder spreads
  425.     dots(i).dx = rd * 10 * (10 - 2 * dots(i).size) * COS(angle)
  426.     dots(i).dy = rd * 10 * (10 - 2 * dots(i).size) * SIN(angle)
  427.     rd = 20 + RND * 70
  428.     dots(i).kolor = _RGBA32(rd, rd, rd, 80)
  429.  
  430. SUB drawship 'simple red iso triangle pointed towards radianAngle
  431.     DIM x1 AS LONG, y1 AS LONG, x2 AS LONG, y2 AS LONG, x3 AS LONG, y3 AS LONG
  432.     'calculate 3 tail points of triangle ship
  433.     x1 = ship.x + 40 * COS(ship.a - pi) '   middle
  434.     y1 = ship.y + 40 * SIN(ship.a - pi) '
  435.     x2 = ship.x + 60 * COS(ship.a + .9 * pi) ' wing
  436.     y2 = ship.y + 60 * SIN(ship.a + .9 * pi)
  437.     x3 = ship.x + 60 * COS(ship.a - .9 * pi) ' other wing
  438.     y3 = ship.y + 60 * SIN(ship.a - .9 * pi)
  439.     ftri ship.x, ship.y, x1, y1, x2, y2, _RGB32(80, 120, 80, 80)
  440.     ftri ship.x, ship.y, x1, y1, x3, y3, _RGB32(60, 100, 60, 80)
  441.     LINE (ship.x, ship.y)-(x1, y1), _RGB32(255, 255, 128)
  442.     LINE (ship.x, ship.y)-(x2, y2), _RGB32(180, 180, 120)
  443.     LINE (ship.x, ship.y)-(x3, y3), _RGB32(180, 180, 120)
  444.  
  445. SUB drawRock (iRock)
  446.     RANDOMIZE USING r(iRock).seed 'this prevents having to save a particular sequence of random number
  447.     DIM dx, dy, rad AS LONG, 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
  448.     DIM x2 AS LONG, y2 AS LONG
  449.     dx = r(iRock).speed * COS(r(iRock).heading)
  450.     dy = r(iRock).speed * SIN(r(iRock).heading) 'update location
  451.     r(iRock).ra = r(iRock).ra + r(iRock).spin
  452.     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
  453.         IF iRock <= rocks THEN newRock iRock ELSE r(iRock).live = 0
  454.         EXIT SUB ' reassigned get out of here
  455.     ELSE
  456.         r(iRock).x = r(iRock).x + dx
  457.         r(iRock).y = r(iRock).y + dy
  458.     END IF
  459.     IF ((r(iRock).x - ship.x) ^ 2 + (r(iRock).y - ship.y) ^ 2) ^ .5 < r(iRock).r + 30 THEN 'rock collides with ship?
  460.         FOR rad = 1 TO 200
  461.             fcirc ship.x, ship.y, rad, _RGB32(255 - rad, 255 - 2 * rad, 0)
  462.             _DISPLAY
  463.             _LIMIT 300
  464.         NEXT
  465.         ship.live = 0
  466.         IF iRock <= rocks THEN newRock iRock ELSE r(iRock).live = 0
  467.         EXIT SUB
  468.     END IF
  469.     FOR j = 10 TO 3 STEP -1 '                  rock drawing (see demo program where developed code)
  470.         rRad = .1 * j * r(iRock).r
  471.         leg = rRad * (RND * .7 + .3)
  472.         x0 = r(iRock).x + leg * COS(r(iRock).ra)
  473.         y0 = r(iRock).y + leg * SIN(r(iRock).ra)
  474.         rc = r(iRock).c + 30 * RND - 15
  475.         c~& = _RGB32(rc + 5, rc - 10, rc + 5)
  476.         x1 = x0
  477.         y1 = y0
  478.         xoff = RND * 20 - 10 + r(iRock).x
  479.         yoff = RND * 20 - 10 + r(iRock).y
  480.         FOR i = 1 TO 12
  481.             leg = rRad * (RND * .35 + .65)
  482.             IF i = 12 THEN
  483.                 x2 = x0: y2 = y0
  484.             ELSE
  485.                 x2 = xoff + leg * COS(i * polyAngle + r(iRock).ra)
  486.                 y2 = yoff + leg * SIN(i * polyAngle + r(iRock).ra)
  487.             END IF
  488.             ftri r(iRock).x, r(iRock).y, x1, y1, x2, y2, c~&
  489.             x1 = x2: y1 = y2
  490.         NEXT
  491.     NEXT
  492.  
  493. SUB newRock (iRock)
  494.     DIM side AS LONG
  495.     RANDOMIZE TIMER * RND 'to avoid making twins
  496.     side = irnd&(1, 4) 'bring rock in from one side, need to set heading according to side
  497.     SELECT CASE side
  498.         CASE 1
  499.             r(iRock).x = -10
  500.             r(iRock).y = rrnd(20, ymax - 20)
  501.             r(iRock).heading = 3 * pi / 2 + RND * pi
  502.         CASE 2
  503.             r(iRock).x = xmax + 10
  504.             r(iRock).y = rrnd(20, ymax - 20)
  505.             r(iRock).heading = pi / 2 + RND * pi
  506.         CASE 3
  507.             r(iRock).x = rrnd(20, xmax - 20)
  508.             r(iRock).y = -10
  509.             r(iRock).heading = RND * pi
  510.         CASE 4
  511.             r(iRock).x = rrnd(20, xmax - 20)
  512.             r(iRock).y = ymax + 10
  513.             r(iRock).heading = pi + RND * pi
  514.     END SELECT
  515.     r(iRock).speed = rrnd(2, 5) 'speed, rotation angle, radius, gray coloring, spin, seed, hit for explosion
  516.     r(iRock).ra = RND * 2 * pi
  517.     r(iRock).r = irnd&(30, 100)
  518.     r(iRock).c = irnd&(10, 60)
  519.     r(iRock).spin = rrnd(-pi / 20, pi / 20)
  520.     r(iRock).seed = INT(RND * 64000) - 32000
  521.     r(iRock).explodeFrame = 0
  522.     r(iRock).live = 1
  523.  
  524. FUNCTION irnd& (n1, n2) 'return an integer between 2 numbers
  525.     DIM l%, h%
  526.     IF n1 > n2 THEN l% = n2: h% = n1 ELSE l% = n1: h% = n2
  527.     irnd& = INT(RND * (h% - l% + 1)) + l%
  528.  
  529. FUNCTION rrnd (n1, n2) ' return number (expecting reals =_single, double, _float depending on default / define setup)
  530.     rrnd = (n2 - n1) * RND + n1
  531.  
  532. SUB fellipse (CX AS LONG, CY AS LONG, xr AS LONG, yr AS LONG, C AS _UNSIGNED LONG)
  533.     IF xr = 0 OR yr = 0 THEN EXIT SUB
  534.     DIM x AS LONG, y AS LONG
  535.     w2 = xr * xr: h2 = yr * yr: h2w2 = h2 * w2
  536.     LINE (CX - xr, CY)-(CX + xr, CY), C, BF
  537.     DO WHILE y < yr
  538.         y = y + 1
  539.         x = SQR((h2w2 - y * y * w2) \ h2)
  540.         LINE (CX - x, CY + y)-(CX + x, CY + y), C, BF
  541.         LINE (CX - x, CY - y)-(CX + x, CY - y), C, BF
  542.     LOOP
  543.  
  544. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  545.     DIM D AS LONG
  546.     STATIC a&
  547.     D = _DEST
  548.     IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32)
  549.     _DEST a&
  550.     _DONTBLEND a& '  '<<<< new 2019-12-16 fix
  551.     PSET (0, 0), K
  552.     _BLEND a& '<<<< new 2019-12-16 fix
  553.     _DEST D
  554.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  555.  
  556. SUB fcirc (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG) 'vince version
  557.     DIM x0 AS LONG, y0 AS LONG, e AS LONG
  558.     x0 = R: y0 = 0: e = 0
  559.     DO WHILE y0 < x0
  560.         IF e <= 0 THEN
  561.             y0 = y0 + 1
  562.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  563.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  564.             e = e + 2 * y0
  565.         ELSE
  566.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  567.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  568.             x0 = x0 - 1: e = e - 2 * x0
  569.         END IF
  570.     LOOP
  571.     LINE (x - R, y)-(x + R, y), C, BF
  572.  

Just need font from OP (original post zip)

 
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 01, 2020, 10:28:49 pm
Wow I like that one better, it's more relaxing to play. You also might want to add a key to press to hide the words and numbers. Then show it when the game is over. Just an idea. :)
Title: Re: b+ Asteroids makeover
Post by: bplus on November 01, 2020, 11:02:11 pm
Wow I like that one better, it's more relaxing to play. You also might want to add a key to press to hide the words and numbers. Then show it when the game is over. Just an idea. :)

Yeah! OK. distracting specially with all that other stuff going on. Also I noticed I wasn't counting hits on Aliens or Boulders (dang I've been spelling it wrong) of Death. Plus I want to see the ship collisions. So another update coming.

Update: Oh man! I am looking at these collisions and I need to relocate my x, y for the ship to it's center.
Title: Re: b+ Asteroids makeover
Post by: bplus on November 02, 2020, 02:05:35 am
M7 now with Splash screen and other screen tweaks, much more info when loose ship in collision, redesigned ship to work better for collision detection.

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

Font from OP is only asset needed.
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 02, 2020, 02:52:07 pm
That's really cool!! My High Score is 15857. :)
Title: Re: b+ Asteroids makeover
Post by: bplus on November 02, 2020, 04:07:26 pm
That's really cool!! My High Score is 15857. :)

Yeah, I haven't been able to get near 38,000 with m7, best is low 20's with this last update.

Last night I was exhausted and poor reaction times... today fresher I tried a couple and can't believe I am not lasting longer with lives 10, 9, 8 always running into some fragment of rock I can't see or I jerk away too far or get caught too close to an edge with new rocks raining in. Man! if you don't make serious points in 10, 9, 8 then you should start over, that is, if you are going for record. I am surprised how long I can last with 1 life left (sometimes)!

Do you like collisions with ship better? (Where now you can see exactly which rock or alien or Boulder of Death did you in.)

Should we save 10 best scores?
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 02, 2020, 05:12:30 pm
10 Best Scores would be awesome! Yeah I like how I can see what I run into. If you REALLY want to work on this a lot more to get it more like the arcade versions, you can remove the mouse movement, except the scroller wheel, and with the left mouse button fire up the engines and the longer you hold it down, the faster you go. It would be harder to play but that's more like the arcade version. You would have to make some kind of exhaust shooting out the back and adding sound to it would help too. But that's just if you want to work on this a lot more. But your version does have an originality to it for sure and it isn't too hard if you get used to the movement.
Title: Re: b+ Asteroids makeover
Post by: bplus on November 02, 2020, 05:28:59 pm
Did arcades use joy sticks? I can't see maneuvering the ship with key presses, even if did something with numeric keypad. A joystick would be perfect because it wouldn't allow you to jump around.

Yeah I saw the rocket thrust flame in the video and tried again with mouse to angle and change position, it's one or the other so far but never say never... come to think, I did a Lander version with simplified rocket thrusters but I wonder if one could possibly switch directions that fast.

I leave sounds to anyone who wants to contribute. I will add them if not .ogg.
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 02, 2020, 05:54:48 pm
Cool about sounds. Well, it doesn't change direction automatically, it's all physics like your lander was probably. Like if you were moving 10 mph and turned and blasted the engines, you would still be going that other direction for a short amount of time and then it would stop and go the new movement. I'm not sure if I know how to make that or not. It wouldn't require the keyboard. The arcade version had a joystick I believe but still worked in this manner. If would have to use both X and Y movement at the same time and just subtract or add X and Y with the new movement. I think I'm going to see if I can make that movement or not on a demo and post it here for you. I might not be able to.
Title: Re: b+ Asteroids makeover
Post by: bplus on November 02, 2020, 06:54:54 pm
I will take a look at Lander thrusters and give it a go as well. Why does spellchecker not like thrusters?

https://www.google.com/search?client=opera&q=spell+thruster&sourceid=opera&ie=UTF-8&oe=UTF-8
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 02, 2020, 07:08:04 pm
Here is a demo I just made for you B+. It's probably a lot like your lander but I wanted to see if I was able to make it myself. If you want to use this code, I'm sure you could make it less code and instead of 4 angles to turn like I have you could make it 8 or as many as you use in your game. Use the scroller wheel (lol spell checker doesn't like "scroller" either) to turn directions and the left mouse button to go. The gun turret shows which direction you are wanting to go. I might turn this into a game. :)
direction2 variable is what angle you are pointing and direction variable is what angle you are actually going.

This isn't like the Asteroids arcade game though. I couldn't figure out how to make it so the physics still makes your guy go one way but slows down as you are wanting to go another way. I thought this would do it but I just noticed it doesn't. But mine does average out the different direction variables so it goes diagonally.

Code: QB64: [Select]
  1. 'Tank Demo using mouse button and mouse scroller wheel.
  2.  
  3. SCREEN _NEWIMAGE(800, 600, 32)
  4. x = 400
  5. y = 300
  6. direction = 1 'North
  7.  
  8.  
  9.     _LIMIT 20
  10.     mouseWheel = 0
  11.         mouseX = _MOUSEX
  12.         mouseY = _MOUSEY
  13.         mouseLeftButton = _MOUSEBUTTON(1)
  14.         mouseRightButton = _MOUSEBUTTON(2)
  15.         mouseMiddleButton = _MOUSEBUTTON(3)
  16.         mouseWheel = mouseWheel + _MOUSEWHEEL
  17.     LOOP
  18.     IF mouseWheel < 0 THEN direction2 = direction2 - 1
  19.     IF mouseWheel > 0 THEN direction2 = direction2 + 1
  20.     IF direction2 > 4 THEN direction2 = 1
  21.     IF direction2 < 1 THEN direction2 = 4
  22.  
  23.     IF direction2 = 1 AND direction = 2 THEN y = y - speed: x = x + speed: amount = amount - 1
  24.     IF direction2 = 1 AND direction = 4 THEN y = y - speed: x = x - speed: amount = amount - 1
  25.     IF direction2 = 1 AND direction = 3 THEN y = y - speed: amount = amount - 1
  26.     IF direction2 = 2 AND direction = 1 THEN x = x + speed: y = y - speed: amount = amount - 1
  27.     IF direction2 = 2 AND direction = 3 THEN x = x + speed: y = y + speed: amount = amount - 1
  28.     IF direction2 = 2 AND direction = 4 THEN x = x + speed: amount = amount - 1
  29.     IF direction2 = 3 AND direction = 2 THEN y = y + speed: x = x + speed: amount = amount - 1
  30.     IF direction2 = 3 AND direction = 4 THEN y = y + speed: x = x - speed: amount = amount - 1
  31.     IF direction2 = 3 AND direction = 1 THEN y = y + speed: amount = amount - 1
  32.     IF direction2 = 4 AND direction = 1 THEN x = x - speed: y = y - speed: amount = amount - 1
  33.     IF direction2 = 4 AND direction = 3 THEN x = x - speed: y = y + speed: amount = amount - 1
  34.     IF direction2 = 4 AND direction = 2 THEN x = x - speed: amount = amount - 1
  35.     IF direction = 1 AND direction2 = 1 THEN y = y - speed: amount = amount - 1
  36.     IF direction = 2 AND direction2 = 2 THEN x = x + speed: amount = amount - 1
  37.     IF direction = 3 AND direction2 = 3 THEN y = y + speed: amount = amount - 1
  38.     IF direction = 4 AND direction2 = 4 THEN x = x - speed: amount = amount - 1
  39.  
  40.     IF direction2 = 1 AND speed = 0 THEN direction = 1
  41.     IF direction2 = 2 AND speed = 0 THEN direction = 2
  42.     IF direction2 = 3 AND speed = 0 THEN direction = 3
  43.     IF direction2 = 4 AND speed = 0 THEN direction = 4
  44.  
  45.     IF mouseLeftButton THEN speed = speed + 5: amount = 100: mouseLeftButton = 0
  46.     IF amount < 50 AND speed > 0 THEN speed = speed - .25
  47.     IF speed < 0 THEN speed = 0: amount = 0
  48.     IF x > 800 THEN x = 0
  49.     IF x < 0 THEN x = 800
  50.     IF y > 600 THEN y = 0
  51.     IF y < 0 THEN y = 600
  52.  
  53.     IF amount = 0 THEN speed = 0: direction = direction2
  54.  
  55.     'Tank
  56.     FOR sz = .25 TO 5 STEP .25
  57.         CIRCLE (x, y), sz, _RGB32(255, 255, 255)
  58.     NEXT sz
  59.  
  60.     'Gun Turrent
  61.     IF direction2 = 1 THEN LINE (x, y)-(x, y - 15), _RGB32(255, 255, 255)
  62.     IF direction2 = 2 THEN LINE (x, y)-(x + 15, y), _RGB32(255, 255, 255)
  63.     IF direction2 = 3 THEN LINE (x, y)-(x, y + 15), _RGB32(255, 255, 255)
  64.     IF direction2 = 4 THEN LINE (x, y)-(x - 15, y), _RGB32(255, 255, 255)
  65.  
  66.     _DISPLAY
  67.     CLS
  68.  
  69.  
  70.  

Title: Re: b+ Asteroids makeover
Post by: Dav on November 02, 2020, 07:49:53 pm
Hey, this is getting better and better! 

- Dav
Title: Re: b+ Asteroids makeover
Post by: bplus on November 02, 2020, 08:36:14 pm
@SierraKen  that's a nice effect and in space you'd never slow down, you'd need reverse thrusters. Still working on my model, I needed a power nap :)

@Dav yeah I like how the aliens turned out, the ship colors, the explosions and of course the Boulders of Death.

Title: Re: b+ Asteroids makeover
Post by: bplus on November 02, 2020, 10:30:05 pm
OK here is my model of flying with rocket thrusters:

up arrow is forward, down reverse thrusters notice wing tips
right arrow is right thrusters notice both tips
left arrow is left thrusters agian notice both wing tips

Code: QB64: [Select]
  1. _TITLE "Thruster Tests" 'b+ 2020-11-02
  2. CONST xmax = 1024, ymax = 700, pi = _PI
  3. SCREEN _NEWIMAGE(xmax, ymax, 32)
  4. _SCREENMOVE 100, 10
  5.  
  6. TYPE shipType
  7.     x AS SINGLE
  8.     y AS SINGLE
  9.     live AS LONG
  10.     speed AS SINGLE
  11.     angle AS SINGLE '   rotated position usu gun left or right (mouse button), maybe up press w or down press z
  12.     thruster AS LONG ' 1 forward, 2 reverse, 3 left , 4 right 0 none for drawing
  13.  
  14. DIM SHARED ship AS shipType
  15. ship.x = xmax / 2: ship.y = ymax / 2: ship.angle = 0
  16. WHILE _KEYDOWN(27) = 0
  17.     CLS
  18.     ship.thruster = 0 'set to zero
  19.     k$ = INKEY$
  20.     IF LEN(k$) = 2 THEN
  21.         SELECT CASE ASC(RIGHT$(k$, 1))
  22.             CASE 72 'up = forward thruster increase speed
  23.                 ship.speed = ship.speed + .1: ship.thruster = 1
  24.             CASE 80 'down = reverse thruster decrease speed yeah will will probably go negative!
  25.                 ship.speed = ship.speed - .1: ship.thruster = 2
  26.             CASE 75 'left = left thruster turn clockwise
  27.                 ship.angle = ship.angle + pi / 6: ship.thruster = 3
  28.             CASE 77 'Right = right thruster turn counter clockwise
  29.                 ship.angle = ship.angle - pi / 6: ship.thruster = 4
  30.         END SELECT
  31.     END IF
  32.     drawship
  33.     _DISPLAY
  34.     _LIMIT 60
  35.  
  36. SUB drawship 'simple red iso triangle pointed towards radianAngle
  37.     DIM x1 AS LONG, y1 AS LONG, x2 AS LONG, y2 AS LONG, x3 AS LONG, y3 AS LONG
  38.     DIM x4 AS LONG, y4 AS LONG, x5 AS LONG, y5 AS LONG, x6 AS LONG, y6 AS LONG
  39.     DIM x7 AS LONG, y7 AS LONG
  40.  
  41.     'locate ship
  42.     ship.x = ship.x + ship.speed * COS(ship.angle)
  43.     ship.y = ship.y + ship.speed * SIN(ship.angle)
  44.     IF ship.x < 0 THEN ship.x = xmax - ABS(ship.x)
  45.     IF ship.x > xmax THEN ship.x = ship.x - xmax
  46.     IF ship.y < 0 THEN ship.y = ymax - ABS(ship.y)
  47.     IF ship.y > ymax THEN ship.y = ship.y - ymax
  48.  
  49.     'calculate 3 points of triangle ship
  50.     fcirc ship.x, ship.y, 30, &H05FFFFFF
  51.     x1 = ship.x + 30 * COS(ship.angle) ' front point
  52.     y1 = ship.y + 30 * SIN(ship.angle) '
  53.     x2 = ship.x + 30 * COS(ship.angle + .6666 * pi) ' wing
  54.     y2 = ship.y + 30 * SIN(ship.angle + .6666 * pi)
  55.     x3 = ship.x + 30 * COS(ship.angle - .6666 * pi) ' other wing
  56.     y3 = ship.y + 30 * SIN(ship.angle - .6666 * pi)
  57.     ftri ship.x, ship.y, x1, y1, x2, y2, _RGB32(80, 120, 80, 80)
  58.     ftri ship.x, ship.y, x1, y1, x3, y3, _RGB32(60, 100, 60, 80)
  59.     LINE (x1, y1)-(ship.x, ship.y), _RGB32(255, 255, 128)
  60.     LINE (x1, y1)-(x2, y2), _RGB32(180, 180, 120)
  61.     LINE (x1, y1)-(x3, y3), _RGB32(180, 180, 120)
  62.  
  63.     SELECT CASE ship.thruster
  64.         CASE 1 'forward apex = ship.x, ship,y  direction = ship.angle + pi
  65.             x4 = ship.x + 25 * COS(ship.angle - 17 / 18 * pi)
  66.             y4 = ship.y + 25 * SIN(ship.angle - 17 / 18 * pi)
  67.             x5 = ship.x + 25 * COS(ship.angle - 19 / 18 * pi)
  68.             y5 = ship.y + 25 * SIN(ship.angle - 19 / 18 * pi)
  69.             ftri ship.x, ship.y, x4, y4, x5, y5, &H99FFFF88
  70.         CASE 2 'reverse apex = x1, y1
  71.             x6 = x2 + 25 * COS(ship.angle + 1 / 18 * pi)
  72.             y6 = y2 + 25 * SIN(ship.angle + 1 / 18 * pi)
  73.             x7 = x2 + 25 * COS(ship.angle - 1 / 18 * pi)
  74.             y7 = y2 + 25 * SIN(ship.angle - 1 / 18 * pi)
  75.             ftri x2, y2, x6, y6, x7, y7, &H99FFFF88
  76.  
  77.             x6 = x3 + 25 * COS(ship.angle + 1 / 18 * pi)
  78.             y6 = y3 + 25 * SIN(ship.angle + 1 / 18 * pi)
  79.             x7 = x3 + 25 * COS(ship.angle - 1 / 18 * pi)
  80.             y7 = y3 + 25 * SIN(ship.angle - 1 / 18 * pi)
  81.             ftri x3, y3, x6, y6, x7, y7, &H99FFFF88
  82.         CASE 3 'left apex = x2, y2
  83.             x6 = x3 + 25 * COS(ship.angle - 17 / 18 * pi)
  84.             y6 = y3 + 25 * SIN(ship.angle - 17 / 18 * pi)
  85.             x7 = x3 + 25 * COS(ship.angle - 19 / 18 * pi)
  86.             y7 = y3 + 25 * SIN(ship.angle - 19 / 18 * pi)
  87.             ftri x3, y3, x6, y6, x7, y7, &H99FFFF88
  88.  
  89.             x6 = x2 + 25 * COS(ship.angle + 1 / 18 * pi)
  90.             y6 = y2 + 25 * SIN(ship.angle + 1 / 18 * pi)
  91.             x7 = x2 + 25 * COS(ship.angle - 1 / 18 * pi)
  92.             y7 = y2 + 25 * SIN(ship.angle - 1 / 18 * pi)
  93.             ftri x2, y2, x6, y6, x7, y7, &H99FFFF88
  94.         CASE 4 'right
  95.             x6 = x2 + 25 * COS(ship.angle - 17 / 18 * pi)
  96.             y6 = y2 + 25 * SIN(ship.angle - 17 / 18 * pi)
  97.             x7 = x2 + 25 * COS(ship.angle - 19 / 18 * pi)
  98.             y7 = y2 + 25 * SIN(ship.angle - 19 / 18 * pi)
  99.             ftri x2, y2, x6, y6, x7, y7, &H99FFFF88
  100.  
  101.             x6 = x3 + 25 * COS(ship.angle + 1 / 18 * pi)
  102.             y6 = y3 + 25 * SIN(ship.angle + 1 / 18 * pi)
  103.             x7 = x3 + 25 * COS(ship.angle - 1 / 18 * pi)
  104.             y7 = y3 + 25 * SIN(ship.angle - 1 / 18 * pi)
  105.             ftri x3, y3, x6, y6, x7, y7, &H99FFFF88
  106.     END SELECT
  107.  
  108. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  109.     DIM D AS LONG
  110.     STATIC a&
  111.     D = _DEST
  112.     IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32)
  113.     _DEST a&
  114.     _DONTBLEND a& '  '<<<< new 2019-12-16 fix
  115.     PSET (0, 0), K
  116.     _BLEND a& '<<<< new 2019-12-16 fix
  117.     _DEST D
  118.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  119.  
  120. SUB fcirc (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG) 'vince version
  121.     DIM x0 AS LONG, y0 AS LONG, e AS LONG
  122.     x0 = R: y0 = 0: e = 0
  123.     DO WHILE y0 < x0
  124.         IF e <= 0 THEN
  125.             y0 = y0 + 1
  126.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  127.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  128.             e = e + 2 * y0
  129.         ELSE
  130.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  131.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  132.             x0 = x0 - 1: e = e - 2 * x0
  133.         END IF
  134.     LOOP
  135.     LINE (x - R, y)-(x + R, y), C, BF
  136.  

Here is our rocket fuel formula: &H99FFFF88  ;-))


UPDATE: THIS IS WRONG!    Press left arrow, turn left not left thruster, right thruster!
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 02, 2020, 11:35:32 pm
That is perfect B+! I can't wait to see it in your game!
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 02, 2020, 11:37:52 pm
You might need to slow down your asteroids though since your spacecraft moves slower now.
Title: Re: b+ Asteroids makeover
Post by: bplus on November 02, 2020, 11:53:58 pm
You might need to slow down your asteroids though since your spacecraft moves slower now.

You ain't kidding!!!!  Man I suck at flying rockets!  Spacebar to start next life because you will be pressing arrows when your ship dies. 

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

I swear this is turning just the wrong way press left arrow...

When I am a bird dipping my wing down left I turn counter clockwise and vice versa.

What do you bird brains think?
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 03, 2020, 12:31:40 am
This is getting to be more real than the arcade version! I like it! You might want to speed up the moving thruster to get out of the way of asteroids quicker, but just a little bit. The turning does take a little bit getting used to since it's opposite when the ship is facing downward than it was facing upward. But to me that's just the fun of the game. And once someone adds sounds to it, it will even be more fun. I'm not sure of a different way you can make it turn, but you can experiment of course.
Title: Re: b+ Asteroids makeover
Post by: bplus on November 03, 2020, 12:54:09 am
OK try this way of turning, to me it seems better, more natural for flying (plus less rocks now and forward reverse thrusters  increased):

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

What I am saying is if I press down on left it seems natural to pivot on left and my right wing swings way around on outside circle, this is counter clockwise so the thrust really needs to be on right wing to move more. I thought right arrow = right thruster side but no, push down on left and thrust on right to swing around.

Title: Re: b+ Asteroids makeover
Post by: Dav on November 03, 2020, 08:26:12 am
Nice!  I like this one better using arrows to control.  Feels more like asteroids to me now. 

- Dav
Title: Re: b+ Asteroids makeover
Post by: bplus on November 03, 2020, 10:22:22 am
Nice!  I like this one better using arrows to control.  Feels more like asteroids to me now. 

- Dav

It's certainly more challenging! 

I am pretty sure I am correct, hit left button to turn left, just like with car or even airplane I imagine.
So to turn left, the right thruster must fire.

So it's not Right Arrow = Right Thruster, right?  ;-) of course not! I wonder if I was doing that with old Lander games?

Also I noticed INKEY$ getting stuck and I am not exactly able to turn on a dime so _KEYDOWN(Arrows)

So life lesson to go forward thrust from behind, to go right thrust from left. Pete might like that :-)
Title: Re: b+ Asteroids makeover
Post by: bplus on November 03, 2020, 02:04:35 pm
I was going to do more with this but have my mind stuck with menu / array displays :)
Checking out new engine and instrument panel response, recalibrating numbers for _Keydown arrow detection as opposed to INKEY$ which seemed to lock up. I noticed I had to pound the right arrow key to get it to turn with the INKEY$ detection method.

Lesson #1 knowing when to stop:

Code: QB64: [Select]
  1. _TITLE "Thruster Tests #2 Flying Lessons" 'b+ 2020-11-03
  2. CONST xmax = 1024, ymax = 700, pi = _PI
  3. SCREEN _NEWIMAGE(xmax, ymax, 32)
  4. _SCREENMOVE 100, 10
  5.  
  6.  
  7. TYPE shipType
  8.     x AS SINGLE
  9.     y AS SINGLE
  10.     live AS LONG
  11.     speed AS SINGLE
  12.     angle AS SINGLE '   rotated position usu gun left or right (mouse button), maybe up press w or down press z
  13.     thruster AS LONG ' 1 forward, 2 reverse, 3 left , 4 right 0 none for drawing
  14.  
  15. DIM SHARED ship AS shipType
  16. ship.x = xmax / 2: ship.y = ymax / 2: ship.angle = 0
  17. WHILE _KEYDOWN(27) = 0
  18.     CLS
  19.     PRINT "The first lesson is seeing how fast you can go without getting close to borders."
  20.     PRINT "In b+ Asteroids borders are where new Asteroids arrive that you can't see coming."
  21.     PRINT "I learn we need a button for full stop! use spacebar?"
  22.     ' Instruments Panel
  23.     ship.thruster = 0 'set to zero   thruster signals drawShip to show exhaust at certain points
  24.  
  25.     ' Imagine ship pointed up for following code
  26.  
  27.     'Up arrow = forward so back thruster
  28.     IF _KEYDOWN(18432) THEN ship.speed = ship.speed + .1: ship.thruster = 1
  29.  
  30.     'Down arrow = reverse thruster decrease speed yeah will will probably go negative!
  31.     IF _KEYDOWN(20480) THEN ship.speed = ship.speed - .1: ship.thruster = 2
  32.  
  33.     'Left Arrow = right thruster turn clockwise  or pivot on left wing tip
  34.     IF _KEYDOWN(19200) THEN ship.angle = ship.angle - pi / 48: ship.thruster = 4
  35.  
  36.     'Right arrow = left thruster turn counter clockwise   or pivot of right wing tip
  37.     IF _KEYDOWN(19712) THEN ship.angle = ship.angle + pi / 48: ship.thruster = 3
  38.  
  39.     IF _KEYDOWN(32) THEN ship.speed = 0
  40.  
  41.     drawship
  42.     _DISPLAY
  43.     _LIMIT 60 ' same as Asteroids Game
  44.  
  45. SUB drawship 'simple red iso triangle pointed towards radianAngle
  46.     DIM x1 AS LONG, y1 AS LONG, x2 AS LONG, y2 AS LONG, x3 AS LONG, y3 AS LONG
  47.     DIM x4 AS LONG, y4 AS LONG, x5 AS LONG, y5 AS LONG, x6 AS LONG, y6 AS LONG
  48.     DIM x7 AS LONG, y7 AS LONG
  49.  
  50.     'locate ship
  51.     ship.x = ship.x + ship.speed * COS(ship.angle)
  52.     ship.y = ship.y + ship.speed * SIN(ship.angle)
  53.     IF ship.x < 0 THEN ship.x = xmax - ABS(ship.x)
  54.     IF ship.x > xmax THEN ship.x = ship.x - xmax
  55.     IF ship.y < 0 THEN ship.y = ymax - ABS(ship.y)
  56.     IF ship.y > ymax THEN ship.y = ship.y - ymax
  57.  
  58.     'calculate 3 points of triangle ship
  59.     fcirc ship.x, ship.y, 30, &H05FFFFFF
  60.     x1 = ship.x + 30 * COS(ship.angle) ' front point
  61.     y1 = ship.y + 30 * SIN(ship.angle) '
  62.     x2 = ship.x + 30 * COS(ship.angle + .6666 * pi) ' wing
  63.     y2 = ship.y + 30 * SIN(ship.angle + .6666 * pi)
  64.     x3 = ship.x + 30 * COS(ship.angle - .6666 * pi) ' other wing
  65.     y3 = ship.y + 30 * SIN(ship.angle - .6666 * pi)
  66.     ftri ship.x, ship.y, x1, y1, x2, y2, _RGB32(80, 120, 80, 80)
  67.     ftri ship.x, ship.y, x1, y1, x3, y3, _RGB32(60, 100, 60, 80)
  68.     LINE (x1, y1)-(ship.x, ship.y), _RGB32(255, 255, 128)
  69.     LINE (x1, y1)-(x2, y2), _RGB32(180, 180, 120)
  70.     LINE (x1, y1)-(x3, y3), _RGB32(180, 180, 120)
  71.  
  72.     SELECT CASE ship.thruster
  73.         CASE 1 'forward apex = ship.x, ship,y  direction = ship.angle + pi
  74.             x4 = ship.x + 25 * COS(ship.angle - 17 / 18 * pi)
  75.             y4 = ship.y + 25 * SIN(ship.angle - 17 / 18 * pi)
  76.             x5 = ship.x + 25 * COS(ship.angle - 19 / 18 * pi)
  77.             y5 = ship.y + 25 * SIN(ship.angle - 19 / 18 * pi)
  78.             ftri ship.x, ship.y, x4, y4, x5, y5, &H99FFFF88
  79.         CASE 2 'reverse apex = x1, y1
  80.             x6 = x2 + 25 * COS(ship.angle + 1 / 18 * pi)
  81.             y6 = y2 + 25 * SIN(ship.angle + 1 / 18 * pi)
  82.             x7 = x2 + 25 * COS(ship.angle - 1 / 18 * pi)
  83.             y7 = y2 + 25 * SIN(ship.angle - 1 / 18 * pi)
  84.             ftri x2, y2, x6, y6, x7, y7, &H99FFFF88
  85.  
  86.             x6 = x3 + 25 * COS(ship.angle + 1 / 18 * pi)
  87.             y6 = y3 + 25 * SIN(ship.angle + 1 / 18 * pi)
  88.             x7 = x3 + 25 * COS(ship.angle - 1 / 18 * pi)
  89.             y7 = y3 + 25 * SIN(ship.angle - 1 / 18 * pi)
  90.             ftri x3, y3, x6, y6, x7, y7, &H99FFFF88
  91.         CASE 3 'left apex = x2, y2
  92.             x6 = x3 + 25 * COS(ship.angle - 17 / 18 * pi)
  93.             y6 = y3 + 25 * SIN(ship.angle - 17 / 18 * pi)
  94.             x7 = x3 + 25 * COS(ship.angle - 19 / 18 * pi)
  95.             y7 = y3 + 25 * SIN(ship.angle - 19 / 18 * pi)
  96.             ftri x3, y3, x6, y6, x7, y7, &H99FFFF88
  97.  
  98.         CASE 4 'right
  99.             x6 = x2 + 25 * COS(ship.angle - 17 / 18 * pi)
  100.             y6 = y2 + 25 * SIN(ship.angle - 17 / 18 * pi)
  101.             x7 = x2 + 25 * COS(ship.angle - 19 / 18 * pi)
  102.             y7 = y2 + 25 * SIN(ship.angle - 19 / 18 * pi)
  103.             ftri x2, y2, x6, y6, x7, y7, &H99FFFF88
  104.     END SELECT
  105.  
  106. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  107.     DIM D AS LONG
  108.     STATIC a&
  109.     D = _DEST
  110.     IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32)
  111.     _DEST a&
  112.     _DONTBLEND a& '  '<<<< new 2019-12-16 fix
  113.     PSET (0, 0), K
  114.     _BLEND a& '<<<< new 2019-12-16 fix
  115.     _DEST D
  116.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  117.  
  118. SUB fcirc (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG) 'vince version
  119.     DIM x0 AS LONG, y0 AS LONG, e AS LONG
  120.     x0 = R: y0 = 0: e = 0
  121.     DO WHILE y0 < x0
  122.         IF e <= 0 THEN
  123.             y0 = y0 + 1
  124.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  125.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  126.             e = e + 2 * y0
  127.         ELSE
  128.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  129.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  130.             x0 = x0 - 1: e = e - 2 * x0
  131.         END IF
  132.     LOOP
  133.     LINE (x - R, y)-(x + R, y), C, BF
  134.  
  135.  
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 03, 2020, 04:10:07 pm
I love the new turning on this. Yes, Space Bar would be a nice automatic stop. I was also thinking, this full version above would be a good Beginner or Easy difficulty because I could play this almost for hours on the same game. In the beginning you could have Easy, Medium, or Hard and have this one for Easy and then increase the amount of asteroids for Medium and Hard. I noticed that the hardest part is trying to see the darkest asteroids. I would make the darkest asteroids a little lighter color, but that's just me. Anyway, I don't mean to be so critical on this game though, just some ideas. :)
Title: Re: b+ Asteroids makeover
Post by: bplus on November 03, 2020, 05:28:10 pm
Roger that, next version I will lighten the rocks (I noticed same).

Thanks @SierraKen  comments, ideas, experiences always welcome! :) I specially appreciate experiences from arcades.

 
Title: Re: b+ Asteroids makeover
Post by: Dav on November 03, 2020, 06:30:31 pm
I like the new turning too.  Really smooth now.  Nice to have a stop button.  If I remember the old arcade version right (I should, I spent a lot of money playing it), the only way to stop moving forward and slow down was to turn the ship around and thrust the other way. 

Funny, what I remember most about the original was the repeating sound that got faster and faster as the level advanced and the enemy ufo attacked, which sometimes made me nervous and mess up .  I'd guess the programmer got that idea from the "jaws" movie which had that chromatic suspense music when the shark attacked. Very effective.

- Dav
Title: Re: b+ Asteroids makeover
Post by: bplus on November 03, 2020, 07:23:22 pm
Oh yeah Jaws! that would be great!

But there was no reverse thrusters in Asteroids?  I am going to watch more videos of this game.

You know allot of times at startup of a new life I wished it was already going forward and I didn't have to worry so much about forward speeds so I could concentrate of steering.

They say sharks have to be constantly moving to breath and birds have to be constantly moving to fly, maybe instead of full stop just a return to a slow constant forward speed?
Title: Re: b+ Asteroids makeover
Post by: bplus on November 04, 2020, 11:21:21 am
Update: I did review Asteroids videos and I found someone with restored Atari 1979 or 80's Arcade Game and he went over the entire machine including trivia on coin boxes and outer detailing. Importantly he showed controls and instructions for them off original machine.

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

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

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

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

There is a question of pumping the key or laying on the key for spinning and firing. If you want to lay on the key then you need _KEYDOWN that can do several keys at once. If you want to pump keys for limited burst you need inkey or _KEYHIT...  anyway the Hyperspace problem had me baffled why I couldn't jump again and again if I wanted. I could jump once per life and maybe if waited long enough (for what?) jump again didn't matter if _KEYHIT, INKEY$ or _KEYDOWN it would only jump once. ??? a head scratcher!
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 04, 2020, 12:24:40 pm
B+, let's see the code, maybe I can find the problem. If it's not a flow problem, then it could be a variable that doesn't change how you need it to. I've noticed in the past that sometimes inkey$ will hold onto its past string amount, which is why I often say a$ = "" after it doesn't need it anymore.
Title: Re: b+ Asteroids makeover
Post by: bplus on November 04, 2020, 01:34:32 pm
Here I've fixed up thrust code for k key, everything is working just right here, now, since last post.

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

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

Title: Re: b+ Asteroids makeover
Post by: bplus on November 04, 2020, 01:42:44 pm
@SierraKen

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

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

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

But if you or anyone can solve the mysterious disappearance of Hyperdrive spacebar  after the first use, I probably would be grateful or disgusted by my blunder ha, ha! But live and learn!
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 04, 2020, 02:33:52 pm
Here you go B+. :) You will hate me when I tell you how I fixed it. It's something you guys have told me not to use more than once in an entire program but it works. I added RANDOMIZE TIMER right before the RND lines. I also changed the INKEY$ to KEYHIT since it seemed to work better, but you can try INKEY$ again if you want. What I found out was that it was actually working every time with KEYHIT (and possibly INKEY$) but it was just going to the same location you started at. For example, if I moved and used it, it went back to where it was before, almost every time. So that meant it was a randomize problem so RANDOMIZE TIMER does the trick. :) For some reason it needed to randomize the timer again probably since it also uses RND in other locations in your program. Oh, as I experimented with different things I also removed XMAX and YMAX and just used your values of it instead to make it easier on the program. That probably doesn't do anything though but I left it there.

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

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

@SierraKen

Brilliant! Thankyou, thankyou, thankyou!

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

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

So you have saved me allot grief today when I install the rest of the controls, one shining gold star for you!
Title: Re: b+ Asteroids makeover
Post by: johnno56 on November 04, 2020, 04:34:15 pm
Suggestion: If the overall "field of view" were larger than the screen image then a 'mini-map' could be added. Resolution of the mini-map could be linked to player health. eg: Full health will show all large and small rocks and ufo's. Poor health only large objects.

Just a thought...

J
Title: Re: b+ Asteroids makeover
Post by: bplus on November 04, 2020, 05:07:06 pm
Thanks @johnno56

I will put your idea on back burner while I try to get Asteroids playing the way I think it should. It may be a proper pilot that we might be waiting for. :)
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 04, 2020, 06:14:27 pm
You're welcome B+, glad I could help. :)
Title: Re: b+ Asteroids makeover
Post by: bplus on November 04, 2020, 11:05:35 pm
OK here is M9 with the new Thrust control and engine installed, this is working nice! Hyperspace jump handy and you can thrust through one border and come out the other side. Just shoot like a maniac!

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

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

Hey 2nd time out with M9 and this!
 
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 04, 2020, 11:59:51 pm
Awesome job! I like the new sounds. I didn't know the SOUND command could have such a high frequency and low time on them. I have one suggestion though if you want to keep working on this. Use the player's score to either speed things up or add asteroids and saucers to them. For example, every 5,000 the speed could increase by a certain amount or another asteroid or saucer is added on the screen. But that's all I will say because this is really good!
Title: Re: b+ Asteroids makeover
Post by: bplus on November 05, 2020, 10:02:46 am
My last post from late last night is missing. Come to think the forum became inaccessible just after but the post was made?

Anyway I had new high score over 84,000.

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

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

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

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

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

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

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

- Dav 
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 05, 2020, 11:58:46 am
Thanks B+, I might tinker around with it later today. Really cool game! Hopefully the final version of this game goes into the Games section of the forum.
Title: Re: b+ Asteroids makeover
Post by: bplus on November 05, 2020, 04:33:16 pm
M10 mods based on latest comments, have it both ways: arrows or AS and K. Fire is continuous why beat the keyboard up? A little score board in top left corner, I've been wondering about rocks being hit PUS score for round PLUS lives update. Constants added for tinkering with speeds and sizes.

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

Title: Re: b+ Asteroids makeover
Post by: johnno56 on November 05, 2020, 06:07:02 pm
Aw man! I was just about to post my new high score, that topped BPlus's 84,000, with my 85,932... When I saw Ken's posting... Ouch! Well done, Ken... (grumble.. grumble..)
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 05, 2020, 06:52:30 pm
LOL Thanks Johno. I guess I've always been good at Asteroids. LOL
Title: Re: b+ Asteroids makeover
Post by: bplus on November 05, 2020, 07:47:27 pm
Holy cow, Ken! Wow, and that's after I put more start rocks back in and increased speeds a bit!

How long did that take? Do you use thrust much? Isn't Hyperspace jump a life saver? ;-)

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

That's funny! My first version here was just turning! (though we were using mouse to point the way) Then someone said we should be able to move the ship, who was that? ;-))  Well I for one am glad we tried more things.
Title: Re: b+ Asteroids makeover
Post by: Dav on November 06, 2020, 07:04:20 am
Since it fires automaticaly now, I thought I'd sit my flashlight on the arrow key a while and see how well it could play.  It played a pretty good game - without batteries even...

- Dav

  [ This attachment cannot be displayed inline in 'Print Page' view ]  
Title: Re: b+ Asteroids makeover
Post by: johnno56 on November 06, 2020, 07:41:23 am
Cool... Now you know how to set it for 'auto-pilot' if you need to take a toilet or coffee break....
Title: Re: b+ Asteroids makeover
Post by: bplus on November 06, 2020, 11:37:55 am
Since it fires automaticaly now, I thought I'd sit my flashlight on the arrow key a while and see how well it could play.  It played a pretty good game - without batteries even...

- Dav

 


Well something tells me this game is too easy ;-))


Cool... Now you know how to set it for 'auto-pilot' if you need to take a toilet or coffee break....

Speaking of auto-pilot, I made one for Snake Game and one for Lunar Lander in JB, hmm....

Well first, we need to make the game a little more challanging hee, hee...
Title: Re: b+ Asteroids makeover
Post by: Dav on November 06, 2020, 01:09:19 pm
It's playing really well.   For more challenge, how about make the ufo shoot back, or when some rocks explode, a few small pieces head towards the ship?

- Dav
Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 06, 2020, 02:23:37 pm
Yeah more little rocks heading toward the ship would be good. Then people might have to dodge them. :) I would also speed the game up a little faster than it does, maybe cut the time in half on how often it speeds up.
Title: Re: b+ Asteroids makeover
Post by: bplus on November 06, 2020, 05:04:49 pm
Does this fix your wagon? ;-))

A little faster rocks and therefore aliens and more rock fragments heading your way along with alien ship paths and they are all starting a little closer to the center, if you like to hang out there be warned...

I also tweaked some other things like tightened the gap between ship and collision object, sort of like to see rock or alien touching ship during collision, closer but not perfect. The flashlight strategy still is a pretty good survival technique.

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

Title: Re: b+ Asteroids makeover
Post by: SierraKen on November 06, 2020, 08:29:45 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. :)
Title: Re: b+ Asteroids makeover
Post by: bplus 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.  
Title: Re: b+ Asteroids makeover
Post by: bplus 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.
Title: Re: b+ Asteroids makeover
Post by: Dav 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
Title: Re: b+ Asteroids makeover
Post by: bplus 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.
Title: Re: b+ Asteroids makeover
Post by: Kiara87 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
Title: Re: b+ Asteroids makeover
Post by: bplus 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.
Title: Re: b+ Asteroids makeover
Post by: Kiara87 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
Title: Re: b+ Asteroids makeover
Post by: bplus 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!
Title: Re: b+ Asteroids makeover
Post by: bplus 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 :-))
Title: Re: b+ Asteroids makeover
Post by: bplus 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.
Title: Re: b+ Asteroids makeover
Post by: MasterGy on April 01, 2021, 02:02:47 pm
works nice! good luck for that !
Title: Re: b+ Asteroids makeover
Post by: bplus 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.