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

0 Members and 1 Guest are viewing this topic.

This topic contains a post which is marked as Best Answer. Press here if you would like to see it.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
b+ Asteroids makeover
« 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.



* b+ Asteroids 2020-10.zip (Filesize: 1.04 MB, Downloads: 277)
« Last Edit: October 27, 2020, 04:23:19 pm by bplus »

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: b+ Asteroids makeover
« Reply #1 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.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #2 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...

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: b+ Asteroids makeover
« Reply #3 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

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: b+ Asteroids makeover
« Reply #4 on: October 28, 2020, 06:41:20 am »
Who doesn't like a good Asteroids game? Another cool version... Nicely done!
Logic is the beginning of wisdom.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #5 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.  

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: b+ Asteroids makeover
« Reply #6 on: October 28, 2020, 01:23:06 pm »
:) If I remember right, the asteroids can break up twice before totally disintagrating.

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: b+ Asteroids makeover
« Reply #7 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


Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #8 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?

;-))

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #9 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 ;-))
« Last Edit: October 29, 2020, 12:05:13 pm by bplus »

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: b+ Asteroids makeover
« Reply #10 on: October 29, 2020, 01:00:47 pm »
It sounds great, can't wait to see it. :)
« Last Edit: October 29, 2020, 01:02:09 pm by SierraKen »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #11 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
« Last Edit: October 29, 2020, 04:32:52 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #12 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?
« Last Edit: October 29, 2020, 09:31:00 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: b+ Asteroids makeover
« Reply #13 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.
« Last Edit: October 30, 2020, 11:46:36 am by bplus »

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: b+ Asteroids makeover
« Reply #14 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. :)