QB64.org Forum

Active Forums => Programs => Topic started by: bplus on July 28, 2019, 11:19:27 am

Title: Invaders bplus style
Post by: bplus on July 28, 2019, 11:19:27 am
I love the play action in Ken's Invader series, so I have abstracted it in my own mod style for further development.

Here is b0_1:
Code: QB64: [Select]
  1. _TITLE "Invaders b0_1" 'Bplus started 2019-07-27 inspired by Ken's fun program series at QB64 Forum
  2.  
  3. CONST xmax = 1200, ymax = 720, PI = 3.141592653589793, PD2 = 1.570796326794897, PT2 = 6.283185307
  4. SCREEN _NEWIMAGE(xmax, ymax, 32)
  5. _SCREENMOVE 100, 20
  6.  
  7. TYPE typeO
  8.     x AS SINGLE
  9.     y AS SINGLE
  10.     xc AS SINGLE
  11.     yc AS SINGLE
  12.     dx AS SINGLE
  13.     dy AS SINGLE
  14.     a AS SINGLE
  15.     v1 AS SINGLE
  16.     v2 AS SINGLE
  17.     size AS SINGLE
  18.     live AS INTEGER
  19.     exploding AS INTEGER
  20.     lastShot AS SINGLE
  21.     c AS _UNSIGNED LONG
  22.  
  23. DIM SHARED o(100) AS typeO, shoot AS INTEGER
  24. DIM i AS INTEGER, j AS INTEGER, kh AS LONG, red
  25. setUp
  26. WHILE o(0).live
  27.     LINE (0, 0)-(xmax, ymax), _RGBA(0, 0, 0, 10), BF
  28.     kh = _KEYHIT
  29.     IF kh = 32 THEN shoot = -1
  30.     IF kh = 18432 THEN o(0).dx = 0
  31.     IF kh = 19200 THEN o(0).dx = -3
  32.     IF kh = 19712 THEN o(0).dx = 3
  33.     _TITLE "Cat's lives: " + STR$(o(0).live)
  34.     FOR i = 0 TO 100
  35.         IF o(i).live <> 0 THEN 'draw everything, update positions, check updated position
  36.             IF i = 0 THEN 'shooter
  37.                 IF o(0).exploding = 0 THEN
  38.                     drawshooter o(i).x
  39.                     IF shoot AND (TIMER(.001) - o(0).lastShot) > .2 THEN
  40.                         newBullet 0, o(0).x, ymax - 60
  41.                     END IF
  42.                     IF o(i).x + o(i).dx > 0 AND o(i).x + o(i).dx < xmax THEN
  43.                         o(i).x = o(i).x + o(i).dx
  44.                     ELSE
  45.                         o(i).dx = -o(i).dx
  46.                     END IF
  47.                 ELSEIF o(i).exploding > 0 THEN
  48.                     o(0).exploding = o(0).exploding - 1
  49.                     IF o(0).exploding = 0 THEN 'exploded enough
  50.                         o(0).live = o(0).live - 1
  51.                         drawshooter o(i).x
  52.                         IF o(0).live = 0 THEN EXIT FOR
  53.                     ELSE
  54.                         red = rand(60, 255)
  55.                         fcirc o(0).x, ymax - 75, o(0).exploding * 6, _RGB32(red, rand(0, red), 0)
  56.                     END IF
  57.                 END IF
  58.             ELSEIF i > 0 AND i < 4 THEN 'enemy ships
  59.                 'from celtic knot model
  60.                 'xReturn = xc + r * (COS(a) + COS(5 * a) / 1.6 + SIN(2 * a) / 3)
  61.                 'yReturn = yc + r * (SIN(a) + SIN(5 * a) / 1.6 + COS(2 * a) / 3)
  62.                 IF o(i).exploding = 0 THEN
  63.                     o(i).x = o(i).xc + 150 * (COS(o(i).a) + COS(o(i).v1 * o(i).a) / 2 + SIN(o(i).v2 * o(i).a) / 3)
  64.                     o(i).y = o(i).yc + 150 * (SIN(o(i).a) + SIN(o(i).v1 * o(i).a) / 2 + COS(o(i).v2 * o(i).a) / 3)
  65.                     fcirc o(i).x, o(i).y, o(i).size, o(i).c
  66.                     o(i).a = o(i).a + PI / 1440
  67.                     IF o(i).xc + o(i).dx > 0 AND o(i).xc + o(i).dx < xmax THEN
  68.                         o(i).xc = o(i).xc + o(i).dx
  69.                     ELSE
  70.                         o(i).dx = -o(i).dx
  71.                     END IF
  72.                     'drop bombs
  73.                     IF TIMER(.001) - o(i).lastShot > 3 THEN
  74.                         newBullet i, o(i).x, o(i).y + o(i).size
  75.                     END IF
  76.                 ELSEIF o(i).exploding > 0 THEN
  77.                     o(i).exploding = o(i).exploding - 1
  78.                     IF o(i).exploding = 0 THEN
  79.                         newEnemy i
  80.                     ELSE
  81.                         red = rand(60, 255)
  82.                         fcirc o(i).x, o(i).y, o(i).exploding * 3, _RGB32(red, rand(0, red), 0)
  83.                     END IF
  84.                 END IF
  85.             ELSEIF i > 3 AND i < 101 THEN 'bullets
  86.                 fcirc o(i).x, o(i).y, o(i).size, o(i).c
  87.                 IF o(i).x + o(i).dx > 0 AND o(i).x + o(i).dx < xmax THEN
  88.                     o(i).x = o(i).x + o(i).dx
  89.                 ELSE
  90.                     o(i).live = 0: o(i).x = -999: o(i).y = -999: o(i).dy = 0
  91.                 END IF
  92.                 IF o(i).y + o(i).dy > 0 AND o(i).y + o(i).dy < ymax THEN
  93.                     IF o(i).dy > 0 THEN o(i).dy = o(i).dy + .1 'gravity
  94.                     o(i).y = o(i).y + o(i).dy
  95.                 ELSE
  96.                     o(i).live = 0: o(i).x = -999: o(i).y = -999: o(i).dy = 0
  97.                 END IF
  98.                 'did this bullet hit anything
  99.                 IF o(i).dy > 0 THEN 'did it hit the shooter
  100.                     IF ((o(i).x - o(0).x) ^ 2 + (o(i).y - o(0).y) ^ 2) ^ .5 <= 50 THEN
  101.                         'explode shooter
  102.                         BEEP
  103.                         o(0).exploding = 20 'signal exploding
  104.                         o(i).live = 0: o(i).x = -999: o(i).y = -999: o(i).dy = 0
  105.                     END IF
  106.                 ELSEIF o(i).dy < 0 AND o(i).c = &HFFFFFFFF THEN 'did it hit the enemy?
  107.                     FOR j = 1 TO 3
  108.                         IF ((o(i).x - o(j).x) ^ 2 + (o(i).y - o(j).y) ^ 2) ^ .5 <= o(j).size + 2 THEN
  109.                             IF o(j).exploding = 0 THEN
  110.                                 o(j).exploding = 20
  111.                                 o(i).live = 0: o(i).x = -999: o(i).y = -999: o(i).dy = 0
  112.                             END IF
  113.                         END IF
  114.                     NEXT
  115.                 END IF 'bullet hit
  116.             END IF 'shooter
  117.         END IF 'live
  118.     NEXT
  119.     _DISPLAY
  120.     _LIMIT 60
  121.  
  122. SUB setUp
  123.     'obj 0 is the player's shooter
  124.     DIM i AS INTEGER
  125.     o(0).x = xmax / 2: o(0).y = ymax - 25
  126.     o(0).live = 9
  127.     FOR i = 1 TO 3 'enemy
  128.         newEnemy i
  129.     NEXT
  130.  
  131. SUB newEnemy (i)
  132.     IF i < 1 OR i > 3 THEN BEEP: EXIT SUB
  133.     o(i).a = RND * PT2: o(i).live = 1: o(i).v1 = rand(2, 19): o(i).v2 = rand(2, 19)
  134.     o(i).size = rand(10, 30): o(i).c = _RGB32(rand(128, 255), rand(0, 128), rand(0, 128))
  135.     o(i).yc = ymax / 2 - 30: o(i).lastShot = TIMER(.003) + .67 * i
  136.     IF RND < .5 THEN
  137.         o(i).xc = 0: o(i).dx = 1
  138.     ELSE
  139.         o(i).xc = xmax: o(i).dx = -1
  140.     END IF
  141.  
  142. SUB newBullet (who, x, y)
  143.     DIM ii AS INTEGER
  144.     FOR ii = 4 TO 100 'find bullet slot
  145.         IF o(ii).live = 0 THEN EXIT FOR 'got slot
  146.     NEXT
  147.     IF ii >= 4 AND ii <= 100 THEN
  148.         o(ii).x = x: o(ii).y = y: o(ii).size = 2: o(ii).live = -1: o(who).lastShot = TIMER(.001)
  149.         IF shoot AND who = 0 THEN
  150.             o(ii).dy = -10: o(ii).c = &HFFFFFFFF
  151.         ELSEIF who > 0 AND who < 4 THEN
  152.             o(ii).dy = 1: o(ii).c = &HFFFFFF00
  153.         END IF
  154.     END IF
  155.     shoot = 0
  156.  
  157. SUB drawshooter (x) 'simple red iso triangle pointed towards radianAngle
  158.     DIM y1, y2, x1, x2
  159.     'calculate 3 points of triangle shooter
  160.     y1 = ymax - 10
  161.     y2 = ymax - 60
  162.     x1 = x - 50
  163.     x2 = x + 50
  164.     fTri x, y1, x1, ymax, x, y2, _RGB(0, 0, 200)
  165.     fTri x, y1, x2, ymax, x, y2, _RGB(0, 0, 200)
  166.     ln x, y1, x1, ymax, _RGB32(255, 255, 128)
  167.     ln x1, ymax, x, y2, _RGB32(255, 255, 128)
  168.     ln x, y1, x2, ymax, _RGB32(255, 255, 128)
  169.     ln x2, ymax, x, y2, _RGB32(255, 255, 128)
  170.     ln x, y1, x, y2, _RGB32(255, 255, 128)
  171.  
  172. FUNCTION rand% (lo%, hi%)
  173.     rand% = INT(RND * (hi% - lo% + 1)) + lo%
  174.  
  175. ' 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
  176. SUB fTri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  177.     DIM a&
  178.     a& = _NEWIMAGE(1, 1, 32)
  179.     _DEST a&
  180.     PSET (0, 0), K
  181.     _DEST 0
  182.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  183.     _FREEIMAGE a& '<<< this is important!
  184.  
  185. SUB ln (x1, y1, x2, y2, K AS _UNSIGNED LONG) 'box frame
  186.     LINE (x1, y1)-(x2, y2), K
  187.  
  188. 'from Steve Gold standard
  189. SUB fcirc (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  190.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  191.     DIM X AS INTEGER, Y AS INTEGER
  192.     Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
  193.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  194.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  195.     WHILE X > Y
  196.         RadiusError = RadiusError + Y * 2 + 1
  197.         IF RadiusError >= 0 THEN
  198.             IF X <> Y + 1 THEN
  199.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  200.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  201.             END IF
  202.             X = X - 1
  203.             RadiusError = RadiusError - X * 2
  204.         END IF
  205.         Y = Y + 1
  206.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  207.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  208.     WEND
  209.  
  210.  

Turn down the volume you are about to be BEEPed to death!
Title: Re: Invaders bplus style
Post by: Ashish on July 28, 2019, 11:52:38 am
Nice Job!
Title: Re: Invaders bplus style
Post by: SierraKen on July 28, 2019, 12:08:35 pm
Pretty neat B+! Awesome graphics. Did you get my newest version that has particle explosions? I added that last night.
Title: Re: Invaders bplus style
Post by: bplus on July 28, 2019, 12:51:00 pm
Pretty neat B+! Awesome graphics. Did you get my newest version that has particle explosions? I added that last night.

Thanks guys,

Yes Ken, if you want, I can dig up some more spectacular exploding code, Bill did some too, way more particles per explosion! Fun stuff, explosions :D

Title: Re: Invaders bplus style
Post by: Pete on July 28, 2019, 01:33:13 pm
Thanks for the acid trip. I ran out of mine in the 60's.

Pete
Title: Re: Invaders bplus style
Post by: bplus on July 28, 2019, 02:51:23 pm
That's pretty my eyesight these days, specially after coding or Sudoku practice all evening.
Title: Re: Invaders bplus style
Post by: bplus on July 28, 2019, 10:07:27 pm
They're back...

Code: QB64: [Select]
  1. _TITLE "Invaders b0_2" 'Bplus started 2019-07-27 inspired by Ken's fun program series
  2.  
  3. CONST xmax = 1200, ymax = 720, PI = 3.141592653589793, PD2 = 1.570796326794897, PT2 = 6.283185307
  4. SCREEN _NEWIMAGE(xmax, ymax, 32)
  5. _SCREENMOVE 100, 20
  6.  
  7. TYPE typeO
  8.     x AS SINGLE
  9.     y AS SINGLE
  10.     xc AS SINGLE
  11.     yc AS SINGLE
  12.     dx AS SINGLE
  13.     dy AS SINGLE
  14.     a AS SINGLE
  15.     lastX AS SINGLE
  16.     lastY AS SINGLE
  17.     v1 AS SINGLE
  18.     v2 AS SINGLE
  19.     size AS SINGLE
  20.     live AS INTEGER
  21.     exploding AS INTEGER
  22.     lastShot AS SINGLE
  23.     c AS _UNSIGNED LONG
  24.  
  25. DIM SHARED o(100) AS typeO, shoot AS INTEGER, points
  26. DIM i AS INTEGER, j AS INTEGER, kh AS LONG, red, again$
  27.  
  28.     setUp
  29.     WHILE o(0).live
  30.         LINE (0, 0)-(xmax, ymax), _RGBA(0, 0, 0, 255), BF
  31.         kh = _KEYHIT
  32.         IF kh = 32 THEN shoot = -1
  33.         IF kh = 18432 THEN o(0).dx = 0
  34.         IF kh = 19200 THEN o(0).dx = -3
  35.         IF kh = 19712 THEN o(0).dx = 3
  36.  
  37.         cText xmax / 2, 30, 20, &HFF009900, "Cat's lives: " + STR$(o(0).live) + "   Cat's Points: " + STR$(points)
  38.         FOR i = 0 TO 100
  39.             IF o(i).live <> 0 THEN 'draw everything, update positions, check updated position
  40.                 IF i = 0 THEN 'shooter
  41.                     IF o(0).exploding = 0 THEN
  42.                         drawshooter o(i).x
  43.                         IF shoot AND (TIMER(.001) - o(0).lastShot) > .2 THEN
  44.                             newBullet 0, o(0).x, ymax - 60
  45.                         END IF
  46.                         IF o(i).x + o(i).dx > 0 AND o(i).x + o(i).dx < xmax THEN
  47.                             o(i).x = o(i).x + o(i).dx
  48.                         ELSE
  49.                             o(i).dx = -o(i).dx
  50.                         END IF
  51.                     ELSEIF o(i).exploding > 0 THEN
  52.                         o(0).exploding = o(0).exploding - 1
  53.                         IF o(0).exploding = 0 THEN 'exploded enough
  54.                             o(0).live = o(0).live - 1
  55.                             drawshooter o(i).x
  56.                             IF o(0).live = 0 THEN EXIT FOR
  57.                         ELSE
  58.                             red = rand(60, 255)
  59.                             fcirc o(0).x, ymax - 75, o(0).exploding * 6, _RGB32(red, rand(0, red), 0)
  60.                         END IF
  61.                     END IF
  62.                 ELSEIF i > 0 AND i < 4 THEN 'enemy ships
  63.                     'from celtic knot model
  64.                     'xReturn = xc + r * (COS(a) + COS(5 * a) / 1.6 + SIN(2 * a) / 3)
  65.                     'yReturn = yc + r * (SIN(a) + SIN(5 * a) / 1.6 + COS(2 * a) / 3)
  66.                     IF o(i).exploding = 0 THEN
  67.                         o(i).lastX = o(i).x: o(i).lastY = o(i).y
  68.                         o(i).x = o(i).xc + 150 * (COS(o(i).a) + COS(o(i).v1 * o(i).a) / 2 + SIN(o(i).v2 * o(i).a) / 3)
  69.                         o(i).y = o(i).yc + 150 * (SIN(o(i).a) + SIN(o(i).v1 * o(i).a) / 2 + COS(o(i).v2 * o(i).a) / 3)
  70.                         'fcirc o(i).x, o(i).y, o(i).size, o(i).c
  71.                         drawRat i
  72.                         o(i).a = o(i).a + PI / 1440
  73.                         IF o(i).xc + o(i).dx > 0 AND o(i).xc + o(i).dx < xmax THEN
  74.                             o(i).xc = o(i).xc + o(i).dx
  75.                         ELSE
  76.                             o(i).dx = -o(i).dx
  77.                         END IF
  78.                         'drop bombs
  79.                         IF TIMER(.001) - o(i).lastShot > 3 THEN
  80.                             newBullet i, o(i).x, o(i).y + o(i).size
  81.                         END IF
  82.                     ELSEIF o(i).exploding > 0 THEN
  83.                         o(i).exploding = o(i).exploding - 1
  84.                         IF o(i).exploding = 0 THEN
  85.                             newEnemy i
  86.                         ELSE
  87.                             red = rand(60, 255)
  88.                             fcirc o(i).x, o(i).y, o(i).exploding * 3, _RGB32(red, rand(0, red), 0)
  89.                         END IF
  90.                     END IF
  91.                 ELSEIF i > 3 AND i < 101 THEN 'bullets
  92.                     fcirc o(i).x, o(i).y, o(i).size, o(i).c
  93.                     IF o(i).x + o(i).dx > 0 AND o(i).x + o(i).dx < xmax THEN
  94.                         o(i).x = o(i).x + o(i).dx
  95.                     ELSE
  96.                         o(i).live = 0: o(i).x = -999: o(i).y = -999: o(i).dy = 0
  97.                     END IF
  98.                     IF o(i).y + o(i).dy > 0 AND o(i).y + o(i).dy < ymax THEN
  99.                         IF o(i).dy > 0 THEN o(i).dy = o(i).dy + .1 'gravity
  100.                         o(i).y = o(i).y + o(i).dy
  101.                     ELSE
  102.                         o(i).live = 0: o(i).x = -999: o(i).y = -999: o(i).dy = 0
  103.                     END IF
  104.                     'did this bullet hit anything
  105.                     IF o(i).dy > 0 THEN 'did it hit the shooter
  106.                         IF ((o(i).x - o(0).x) ^ 2 + (o(i).y - o(0).y) ^ 2) ^ .5 <= 50 THEN
  107.                             'explode shooter
  108.                             BEEP
  109.                             o(0).exploding = 20 'signal exploding
  110.                             o(i).live = 0: o(i).x = -999: o(i).y = -999: o(i).dy = 0
  111.                         END IF
  112.                     ELSEIF o(i).dy < 0 AND o(i).c = &HFFFFFFFF THEN 'did it hit the enemy?
  113.                         FOR j = 1 TO 3
  114.                             IF ((o(i).x - o(j).x) ^ 2 + (o(i).y - o(j).y) ^ 2) ^ .5 <= o(j).size + 2 THEN
  115.                                 IF o(j).exploding = 0 THEN
  116.                                     o(j).exploding = 20
  117.                                     points = points + 50 - o(j).size
  118.                                     o(i).live = 0: o(i).x = -999: o(i).y = -999: o(i).dy = 0
  119.                                 END IF
  120.                             END IF
  121.                         NEXT
  122.                     END IF 'bullet hit
  123.                 END IF 'shooter
  124.             END IF 'live
  125.         NEXT
  126.         _DISPLAY
  127.         _LIMIT 60
  128.     WEND
  129.     CLS: _DISPLAY: _DELAY 2.5: _KEYCLEAR ' stop hammer'n the keys!  ;-))
  130.     topTen points
  131.     _KEYCLEAR
  132.     PRINT: INPUT "Press enter to go again, any other, eg q, to quit "; again$
  133. LOOP UNTIL LEN(again$)
  134.  
  135. SUB setUp
  136.     'obj 0 is the player's shooter
  137.     DIM i AS INTEGER
  138.     ERASE o
  139.     points = 0
  140.     o(0).x = xmax / 2: o(0).y = ymax - 25
  141.     o(0).live = 9
  142.     FOR i = 1 TO 3 'enemy
  143.         newEnemy i
  144.     NEXT
  145.  
  146. SUB newEnemy (i)
  147.     DIM r, g, b
  148.     IF i < 1 OR i > 3 THEN BEEP: EXIT SUB
  149.     o(i).a = RND * PT2: o(i).live = 1: o(i).v1 = rand(2, 19): o(i).v2 = rand(2, 19)
  150.     r = rand(128, 255): g = rand(0, .5 * r): b = rand(0, .25 * r)
  151.     o(i).size = rand(10, 45): o(i).c = _RGB32(r, g, b)
  152.     o(i).yc = ymax / 2 - 30: o(i).lastShot = TIMER(.003) + .67 * i
  153.     IF RND < .5 THEN
  154.         o(i).xc = 0: o(i).dx = 1
  155.     ELSE
  156.         o(i).xc = xmax: o(i).dx = -1
  157.     END IF
  158.  
  159. SUB newBullet (who, x, y)
  160.     DIM ii AS INTEGER
  161.     FOR ii = 4 TO 100 'find bullet slot
  162.         IF o(ii).live = 0 THEN EXIT FOR 'got slot
  163.     NEXT
  164.     IF ii >= 4 AND ii <= 100 THEN
  165.         o(ii).x = x: o(ii).y = y: o(ii).size = 2: o(ii).live = -1: o(who).lastShot = TIMER(.001)
  166.         IF shoot AND who = 0 THEN
  167.             o(ii).dy = -10: o(ii).c = &HFFFFFFFF
  168.         ELSEIF who > 0 AND who < 4 THEN
  169.             o(ii).dy = 1: o(ii).c = &HFFFFFF00
  170.         END IF
  171.     END IF
  172.     shoot = 0
  173.  
  174. SUB drawRat (i)
  175.     DIM noseX, noseY, neckX, neckY, tailX, tailY, earLX, earLY, earRX, earRY, wX, wY, rh
  176.     rh = _ATAN2(o(i).y - o(i).lastY, o(i).x - o(i).lastX)
  177.     noseX = o(i).x + 2 * o(i).size * COS(rh)
  178.     noseY = o(i).y + 2 * o(i).size * SIN(rh)
  179.     neckX = o(i).x + .75 * o(i).size * COS(rh)
  180.     neckY = o(i).y + .75 * o(i).size * SIN(rh)
  181.     tailX = o(i).x + 2 * o(i).size * COS(rh + _PI)
  182.     tailY = o(i).y + 2 * o(i).size * SIN(rh + _PI)
  183.     earLX = o(i).x + o(i).size * COS(rh - _PI(1 / 12))
  184.     earLY = o(i).y + o(i).size * SIN(rh - _PI(1 / 12))
  185.     earRX = o(i).x + o(i).size * COS(rh + _PI(1 / 12))
  186.     earRY = o(i).y + o(i).size * SIN(rh + _PI(1 / 12))
  187.     fcirc o(i).x, o(i).y, .65 * o(i).size, o(i).c
  188.     fcirc neckX, neckY, o(i).size * .3, o(i).c
  189.     fTri noseX, noseY, earLX, earLY, earRX, earRY, o(i).c
  190.     fcirc earLX, earLY, o(i).size * .3, o(i).c
  191.     fcirc earRX, earRY, o(i).size * .3, o(i).c
  192.     wX = .5 * o(i).size * COS(rh - _PI(11 / 18))
  193.     wY = .5 * o(i).size * SIN(rh - _PI(11 / 18))
  194.     ln noseX + wX, noseY + wY, noseX - wX, noseY - wY, o(i).c
  195.     wX = .5 * o(i).size * COS(rh - _PI(7 / 18))
  196.     wY = .5 * o(i).size * SIN(rh - _PI(7 / 18))
  197.     ln noseX + wX, noseY + wY, noseX - wX, noseY - wY, o(i).c
  198.     ln o(i).x, o(i).y, tailX, tailY, o(i).c
  199.  
  200. SUB drawshooter (x) 'simple red iso triangle pointed towards radianAngle
  201.     DIM y1, y2, x1, x2
  202.     'calculate 3 points of triangle shooter
  203.     y1 = ymax - 10
  204.     y2 = ymax - 60
  205.     x1 = x - 50
  206.     x2 = x + 50
  207.     fTri x, y1, x1, ymax, x, y2, _RGB(0, 0, 200)
  208.     fTri x, y1, x2, ymax, x, y2, _RGB(0, 0, 200)
  209.     ln x, y1, x1, ymax, _RGB32(255, 255, 128)
  210.     ln x1, ymax, x, y2, _RGB32(255, 255, 128)
  211.     ln x, y1, x2, ymax, _RGB32(255, 255, 128)
  212.     ln x2, ymax, x, y2, _RGB32(255, 255, 128)
  213.     ln x, y1, x, y2, _RGB32(255, 255, 128)
  214.  
  215. SUB topTen (compareScore AS INTEGER)
  216.     DIM fName$, n, Names$(1 TO 10), scores(1 TO 10), name$, score AS INTEGER, settleScore, i
  217.  
  218.     fName$ = "Top 10 Scores.txt" '<<<  since this is toolbox code change this as needed for app
  219.     CLS: PRINT: PRINT "Top Ten Scorers and Scores:"
  220.     IF _FILEEXISTS(fName$) THEN
  221.         OPEN fName$ FOR INPUT AS #1
  222.         WHILE EOF(1) = 0 AND n < 10
  223.             n = n + 1
  224.             INPUT #1, name$
  225.             INPUT #1, score
  226.             IF compareScore >= score AND settleScore = 0 THEN
  227.                 PRINT "You have made the Top Ten!"
  228.                 INPUT "Type your name here: ", Names$(n)
  229.                 scores(n) = compareScore
  230.                 settleScore = -1
  231.                 n = n + 1
  232.                 IF n <= 10 THEN Names$(n) = name$: scores(n) = score
  233.             ELSE
  234.                 scores(n) = score: Names$(n) = name$
  235.             END IF
  236.         WEND
  237.         CLOSE #1
  238.         IF n < 10 AND settleScore = 0 THEN
  239.             PRINT "There is a slot open for your name and score."
  240.             INPUT "Type your name here: ", name$
  241.             IF name$ <> "" THEN n = n + 1: Names$(n) = name$: scores(n) = compareScore
  242.         END IF
  243.         OPEN fName$ FOR OUTPUT AS #1
  244.         FOR i = 1 TO n
  245.             PRINT #1, Names$(i): PRINT #1, scores(i)
  246.             PRINT i, Names$(i), scores(i)
  247.         NEXT
  248.         CLOSE #1
  249.         INPUT "That's the list, press Enter to continue... "; name$
  250.     ELSE
  251.         PRINT "You are first into file!"
  252.         INPUT "Type your name here:"; name$
  253.         OPEN fName$ FOR OUTPUT AS #1
  254.         PRINT #1, name$: PRINT #1, compareScore
  255.         CLOSE #1
  256.     END IF
  257.  
  258. 'center the text
  259. SUB cText (x, y, textHeight, K AS _UNSIGNED LONG, txt$)
  260.     DIM fg AS _UNSIGNED LONG, cur&, I&, mult, xlen
  261.     fg = _DEFAULTCOLOR
  262.     'screen snapshot
  263.     cur& = _DEST
  264.     I& = _NEWIMAGE(8 * LEN(txt$), 16, 32)
  265.     _DEST I&
  266.     COLOR K, _RGBA32(0, 0, 0, 0)
  267.     _PRINTSTRING (0, 0), txt$
  268.     mult = textHeight / 16
  269.     xlen = LEN(txt$) * 8 * mult
  270.     _PUTIMAGE (x - .5 * xlen, y - .5 * textHeight)-STEP(xlen, textHeight), I&, cur&
  271.     COLOR fg
  272.     _FREEIMAGE I&
  273.  
  274. FUNCTION rand% (lo%, hi%)
  275.     rand% = INT(RND * (hi% - lo% + 1)) + lo%
  276.  
  277. ' 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
  278. SUB fTri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  279.     DIM a&
  280.     a& = _NEWIMAGE(1, 1, 32)
  281.     _DEST a&
  282.     PSET (0, 0), K
  283.     _DEST 0
  284.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  285.     _FREEIMAGE a& '<<< this is important!
  286.  
  287. SUB ln (x1, y1, x2, y2, K AS _UNSIGNED LONG) 'box frame
  288.     LINE (x1, y1)-(x2, y2), K
  289.  
  290. 'from Steve Gold standard
  291. SUB fcirc (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  292.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  293.     DIM X AS INTEGER, Y AS INTEGER
  294.     Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
  295.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  296.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  297.     WHILE X > Y
  298.         RadiusError = RadiusError + Y * 2 + 1
  299.         IF RadiusError >= 0 THEN
  300.             IF X <> Y + 1 THEN
  301.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  302.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  303.             END IF
  304.             X = X - 1
  305.             RadiusError = RadiusError - X * 2
  306.         END IF
  307.         Y = Y + 1
  308.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  309.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  310.     WEND
  311.  
Title: Re: Invaders bplus style
Post by: Pete on July 29, 2019, 01:44:43 am
Ah, you decided to ratchet it up a bit. Well, I've had enough rat-chet for one day, thank you very much. Got to around 2000 pts, but after you type your name, it doesn't show you your final score or position.  Other than that, it functions great, except I swear I hit the little varmints at times and they don't explode. In fact, that makes it just like the arcade games of old. YOu'd swear you hit them, but nah, they just keep gunning for ya!

Pete
Title: Re: Invaders bplus style
Post by: TempodiBasic on July 29, 2019, 07:32:20 am
Hi Bplus
fine RatInvaders!...

but why it seems that they fire from the bottom side of body? And why do they die if you hit their bottom side?
It is possible that they have a retro-problem (back-problem)  :-)

It was a joke,
thanks to share
Title: Re: Invaders bplus style
Post by: johnno56 on July 29, 2019, 09:51:12 am
Cool.... Maze refugees.... Nicely done!
Title: Re: Invaders bplus style
Post by: bplus on July 29, 2019, 10:50:48 am
Ah, you decided to ratchet it up a bit. Well, I've had enough rat-chet for one day, thank you very much. Got to around 2000 pts, but after you type your name, it doesn't show you your final score or position.  Other than that, it functions great, except I swear I hit the little varmints at times and they don't explode. In fact, that makes it just like the arcade games of old. YOu'd swear you hit them, but nah, they just keep gunning for ya!

Pete

OK, I will fix the ending with big "Game Over" text message in middle and then freeze/delay before Top Ten review.

Sorry, I am so use to targeting the rat butts, I don't expect a hit to register anywhere else... the hits are based of main radius distance to center of butt, but I can increase... still, if you got to 2000 you are doing way better than I! My best score filling up Top Ten list was 1500+.

Hi Bplus
fine RatInvaders!...

but why it seems that they fire from the bottom side of body? And why do they die if you hit their bottom side?
It is possible that they have a retro-problem (back-problem)  :-)

It was a joke,
thanks to share

Joke, yeah, the rats eat nuclear waste and have deadly excrement! (Which also explains why they fly sideways!) I think you got it! :)

I guess I do have to increase Radius of a hit but do aim for their backsides.

Cool.... Maze refugees.... Nicely done!

LOL "Maze refugees" :)

Thanks all for your feed back, I will make edits to posted code.

Title: Re: Invaders bplus style
Post by: SierraKen on July 29, 2019, 01:17:09 pm
LOL cool game! You can add some falling cheese to get a free shooter if you want. I thought about something like that myself, but starting with 5 shooters was plenty. :)

  ()()             ____
  (..)            /|o     |
  /\/\          /o|    o|
c\db/o...  /o_|_o_| 
Title: Re: Invaders bplus style
Post by: TempodiBasic on July 29, 2019, 01:54:03 pm
Hi Bplus

about
Quote
Joke, yeah, the rats eat nuclear waste and have deadly excrement! (Which also explains why they fly sideways!) I think you got it! :)
I find this your storyboard very cool!
Please don't enlarge the radius... it can be that SpaceMutantRats are they are imperforable and their back explodes by vibration done from collision between back and the missile.
What do you tink about it?
Title: Re: Invaders bplus style
Post by: bplus on July 29, 2019, 02:33:48 pm
LOL cool game! You can add some falling cheese to get a free shooter if you want. I thought about something like that myself, but starting with 5 shooters was plenty. :)

  ()()             ____
  (..)            /|o     |
  /\/\          /o|    o|
c\db/o...  /o_|_o_|

Nice! Instead of Big Boss, I use Big Cheese! It just so happens I do have cheese making code. ;-))
(Some of have seen these rats before.) Actually I had an idea for a little surprise equivalent to a Boss break from the triple threats, sort of an opposite of Boss...

Hi Bplus

about I find this your storyboard very cool!
Please don't enlarge the radius... it can be that SpaceMutantRats are they are imperforable and their back explodes by vibration done from collision between back and the missile.
What do you tink about it?

Yes! as a matter of fact I tried increasing hit radius by a percentage of rat size and it sucked. The small ones still impossible to eRATicate compared to big ones which are so much easier. I decided to try just a flat 10 pixel space of grace because the shooters bullets move 10 pixels between frames and that is most likely cause of misses that shouldn't be.

Storyboard!?! hmm... well as far as explaining explosions because you hit there butts and nothing happens if you hit their heads, I say that's because all the explosive nuclear waste builds up in the bowels of their ships and the "heads" are just decoys to fool human shooters. ;-))

I am adding a 1 point charge for each bullet used and have begun tracking hit% per bullet, I think I might give bonus points at end of game for good %'s and deduct for machine gun Kelly's. I am also considering a hit rate by duration of game, to penalize that player who waits and waits for perfect kill shot. Ah! here is where a free shooter reward belongs!

What do you think?

You all should know I started this because I wanted to see bullets colliding with bullets and exploding. Have yet to get to that.
Title: Re: Invaders bplus style
Post by: SMcNeill on July 29, 2019, 02:42:31 pm
Storyboard:  Aliens invade the world!

After intercepting our broadcast transmissions of Tom and Jerry shows, Aliens decide that mice are the dominant life-form upon our planet.  Though their ships are circular in design (as all good UFOs should be), they have a “mouse cloaking device” which produces a 3-dimensional hologram around the ship.  Attacking the head causes the bullet to pass harmlessly through the hologram, doing zero damage to the actual alien spaceship.  Only by targeting the rear of the hologram can actual damage be accrued to destroy the alien ship...
Title: Re: Invaders bplus style
Post by: bplus on July 29, 2019, 02:49:24 pm
Storyboard:  Aliens invade the world!

After intercepting our broadcast transmissions of Tom and Jerry shows, Aliens decide that mice are the dominant life-form upon our planet.  Though their ships are circular in design (as all good UFOs should be), they have a “mouse cloaking device” which produces a 3-dimensional hologram around the ship.  Attacking the head causes the bullet to pass harmlessly through the hologram, doing zero damage to the actual alien spaceship.  Only by targeting the rear of the hologram can actual damage be accrued to destroy the alien ship...

Steve, you're hired! :)
Title: Re: Invaders bplus style
Post by: bplus on July 29, 2019, 11:23:16 pm
OK another overhaul. Along with changes talked about earlier I added sound effects.

"Game Over" across the screen is very effective signal for cease fire. And I ask for go again when exiting the Top Ten sub. This saves player from having to do 2 key press answers back to back.

There is a whole different method to calculation of hits to ships, ironically it is like an idea Codeguy had that I shot down because it was flawed for the intended app. Here, because the the shots are straight up and down it works and probably much faster.

Man I got stuck with a bug that was allowing a shot ship to be shot over and over. Took me awhile to loose that bug, really hacked up the code to loose it. It seems to be gone now...

You might want to delete old Top Ten file because scoring is different.

So here is b0.3:
Code: QB64: [Select]
  1. _TITLE "Invaders b0_3" 'Bplus started 2019-07-27 inspired by Ken's fun program series
  2.  
  3. ' 2019-07-29 from feed back fix game ending with big "Game Over" sign and delay before Top Ten.
  4. ' Show score to compare with Top Ten Numbers.
  5. ' Change the way hits are calculated, use method that avoids distance function or ABS.
  6. ' Change TopTen sub to TopTenGoAgain$ function to also get Play Again reply.
  7.  
  8. 'OK let's start charging for bullets! 1 point per... and do a hit % to reward skillful shooting
  9. 'change BEEPs to SOUNDS, add more to report, Game Over signals end of game, TopTen does go again.
  10.  
  11. CONST xmax = 1200, ymax = 720, PI = 3.141592653589793, PD2 = 1.570796326794897, PT2 = 6.283185307
  12. SCREEN _NEWIMAGE(xmax, ymax, 32)
  13. _SCREENMOVE 100, 20
  14.  
  15. TYPE typeO
  16.     x AS SINGLE
  17.     y AS SINGLE
  18.     xc AS SINGLE
  19.     yc AS SINGLE
  20.     dx AS SINGLE
  21.     dy AS SINGLE
  22.     a AS SINGLE
  23.     lastX AS SINGLE
  24.     lastY AS SINGLE
  25.     v1 AS SINGLE
  26.     v2 AS SINGLE
  27.     size AS SINGLE
  28.     live AS INTEGER
  29.     exploding AS INTEGER
  30.     lastShot AS SINGLE
  31.     c AS _UNSIGNED LONG
  32.  
  33. DIM SHARED o(100) AS typeO, shoot AS INTEGER, points AS INTEGER, bullets AS INTEGER, hits AS INTEGER
  34. DIM i AS INTEGER, j AS INTEGER, kh AS LONG, red AS INTEGER, again$
  35.     setUp
  36.     WHILE o(0).live
  37.         LINE (0, 0)-(xmax, ymax), _RGBA(0, 0, 0, 255), BF
  38.         kh = _KEYHIT
  39.         IF kh = 32 THEN shoot = -1
  40.         IF kh = 18432 THEN o(0).dx = 0
  41.         IF kh = 19200 THEN o(0).dx = -3
  42.         IF kh = 19712 THEN o(0).dx = 3
  43.         report
  44.  
  45.         'dead ships and bullets? but still exploding  this separated out because ships are getting hit more than once while exploding
  46.         FOR i = 1 TO 3
  47.             IF o(i).exploding THEN
  48.                 o(i).exploding = o(i).exploding - 1
  49.                 IF o(i).exploding = 0 THEN
  50.                     newEnemy i
  51.                 ELSE 'draw explosion
  52.                     SOUND 1000 - o(i).size * 3 + (21 - o(i).exploding) * 10, .1
  53.                     red = rand(60, 255)
  54.                     fcirc o(i).x, o(i).y, o(i).exploding * 3, _RGB32(red, rand(0, red), 0)
  55.                 END IF
  56.             END IF 'i = x
  57.         NEXT
  58.         'bullets
  59.         FOR i = 4 TO 100
  60.             IF o(i).exploding THEN
  61.                 o(i).exploding = o(i).exploding - 1
  62.                 SOUND 1600, .05
  63.                 red = rand(60, 255)
  64.                 fcirc o(i).x, o(i).y, o(i).exploding, _RGB32(red, rand(0, red), 0)
  65.             END IF
  66.         NEXT
  67.  
  68.         FOR i = 0 TO 100
  69.             IF o(i).live <> 0 THEN 'draw everything, update positions, check updated position
  70.                 IF i = 0 THEN 'shooter
  71.                     IF o(0).exploding = 0 THEN
  72.                         drawshooter o(i).x
  73.                         IF shoot AND (TIMER(.001) - o(0).lastShot) > .1 THEN '.2 is this the cause of hitting a ship twice?
  74.                             newBullet 0, o(0).x, ymax - 60
  75.                         END IF
  76.                         IF o(i).x + o(i).dx > 0 AND o(i).x + o(i).dx < xmax THEN
  77.                             o(i).x = o(i).x + o(i).dx
  78.                         ELSE
  79.                             o(i).dx = -o(i).dx
  80.                         END IF
  81.                     ELSEIF o(0).exploding THEN 'exploded enough
  82.                         o(i).exploding = o(i).exploding - 1
  83.                         IF o(i).exploding = 0 THEN 'no longer exploding
  84.                             o(0).live = o(0).live - 1
  85.                             IF o(0).live = 0 THEN
  86.                                 fcirc o(0).x, ymax - 75, 50, &HFF770000
  87.                                 report
  88.                                 EXIT FOR
  89.                             ELSE
  90.                                 drawshooter o(i).x
  91.                             END IF
  92.                         ELSE 'exploding
  93.                             SOUND 400 + o(0).exploding * 7, .3
  94.                             red = rand(60, 255)
  95.                             fcirc o(0).x, ymax - 75, o(0).exploding * 6, _RGB32(red, rand(0, red), 0)
  96.                         END IF
  97.                     END IF
  98.  
  99.                 ELSEIF i > 0 AND i < 4 THEN 'enemy ships
  100.                     'update coodinates
  101.                     o(i).lastX = o(i).x: o(i).lastY = o(i).y
  102.                     o(i).x = o(i).xc + 150 * (COS(o(i).a) + COS(o(i).v1 * o(i).a) / 2 + SIN(o(i).v2 * o(i).a) / 3)
  103.                     o(i).y = o(i).yc + 150 * (SIN(o(i).a) + SIN(o(i).v1 * o(i).a) / 2 + COS(o(i).v2 * o(i).a) / 3)
  104.                     drawRat i
  105.                     o(i).a = o(i).a + PI / 1440
  106.                     IF o(i).xc + o(i).dx > 0 AND o(i).xc + o(i).dx < xmax THEN
  107.                         o(i).xc = o(i).xc + o(i).dx
  108.                     ELSE
  109.                         o(i).dx = -o(i).dx
  110.                     END IF
  111.                     'drop bombs
  112.                     IF TIMER(.001) - o(i).lastShot > 3 THEN
  113.                         newBullet i, o(i).x, o(i).y + o(i).size
  114.                     END IF
  115.  
  116.                 ELSEIF i > 3 AND i < 101 THEN 'bullets
  117.                     fcirc o(i).x, o(i).y, o(i).size, o(i).c
  118.                     IF o(i).y + o(i).dy > 0 AND o(i).y + o(i).dy < ymax THEN
  119.                         IF o(i).dy > 0 THEN o(i).dy = o(i).dy + .1 'gravity
  120.                         o(i).y = o(i).y + o(i).dy
  121.                     ELSE
  122.                         o(i).live = 0
  123.                     END IF
  124.  
  125.                     'did this bullet hit anything
  126.                     IF o(i).dy > 0 THEN 'did it hit the shooter
  127.                         IF (o(0).x - o(0).size <= o(i).x) AND (o(i).x <= o(0).x + o(0).size) THEN
  128.                             IF (o(0).y - o(0).size <= o(i).y) AND (o(i).y <= o(0).y + o(0).size + 20) THEN
  129.                                 IF o(0).exploding = 0 AND o(0).live THEN
  130.                                     SOUND 400 + 5 * 20, .1
  131.                                     o(0).exploding = 20 'signal exploding
  132.                                     o(i).live = 0 'kill bullet
  133.                                 END IF
  134.                             END IF
  135.                         END IF
  136.                     ELSEIF o(i).dy < 0 THEN 'did it hit the enemy?
  137.                         FOR j = 1 TO 3
  138.                             IF (o(j).x - o(j).size <= o(i).x) AND (o(i).x <= o(j).x + o(j).size) THEN 'is x right
  139.                                 IF (o(j).y - o(j).size - 5 < o(i).y) AND (o(i).y <= o(j).y + o(j).size + 5) THEN 'is y right
  140.                                     IF o(j).exploding = 0 AND o(j).live <> 0 THEN 'ship not exploding already
  141.                                         o(j).exploding = 20
  142.                                         SOUND 800 - o(i).size * 3, .1
  143.                                         points = points + 50 - o(j).size
  144.                                         hits = hits + 1
  145.                                         o(i).live = 0: o(j).live = 0 'kill bullet and ship
  146.                                     END IF 'if not exploding already
  147.                                 END IF 'if y is right
  148.                             END IF 'if x is right
  149.                         NEXT
  150.  
  151.                         'finally bullet versus bullet!!  remember these bullets (i) are headed up
  152.                         FOR j = i + 1 TO 100 ' find only those going in different directions
  153.                             IF o(j).dy > 0 THEN 'look for bullets headed down
  154.                                 IF o(j).live THEN
  155.                                     IF o(j).x - 3 <= o(i).x AND o(i).x <= o(j).x + 3 THEN 'is x right
  156.                                         IF (o(j).y - 8 <= o(i).y) AND (o(i).y <= o(j).y + o(j).dy) THEN 'is y right  why 16 gravity accums
  157.                                             fcirc o(i).x, o(i).y, 200, &HFFFFFFFF
  158.                                             o(i).live = 0: o(j).live = 0
  159.                                             o(i).exploding = 10
  160.                                             SOUND 2800, 1
  161.                                         END IF 'if y is right
  162.                                     END IF 'if x is right
  163.                                 END IF 'both still live
  164.                             END IF 'bullets going in opposite directions
  165.                         NEXT
  166.                     END IF 'bullet hit
  167.                 END IF 'shooter
  168.             END IF 'live
  169.         NEXT
  170.         _DISPLAY
  171.         _LIMIT 60
  172.     WEND
  173.     cText xmax / 2, ymax / 2, 128, &HFFFF5500, "Game Over"
  174.     _DISPLAY: _DELAY 2.5: _KEYCLEAR ' stop hammer'n the keys!  ;-))
  175.     again$ = topTenGoAgain$(points)
  176. LOOP UNTIL LEN(again$)
  177.  
  178. SUB setUp
  179.     'obj 0 is the player's shooter
  180.     DIM i AS INTEGER
  181.     ERASE o
  182.     points = 0: bullets = 0: hits = 0
  183.     o(0).x = xmax / 2: o(0).y = ymax - 60: o(0).size = 50
  184.     o(0).live = 10
  185.     FOR i = 1 TO 3 'enemy
  186.         newEnemy i
  187.     NEXT
  188.  
  189. SUB newEnemy (i)
  190.     DIM r, g, b
  191.     IF i < 1 OR i > 3 THEN BEEP: EXIT SUB
  192.     o(i).a = RND * PT2: o(i).live = 1: o(i).v1 = rand(2, 19): o(i).v2 = rand(2, 19)
  193.     r = rand(128, 255): g = rand(0, .5 * r): b = rand(0, .5 * g)
  194.     o(i).size = rand(10, 45): o(i).c = _RGB32(r, g, b)
  195.     o(i).yc = ymax / 2 - 30: o(i).lastShot = TIMER(.003) + i
  196.     IF RND < .5 THEN
  197.         o(i).xc = 0: o(i).dx = 1
  198.     ELSE
  199.         o(i).xc = xmax: o(i).dx = -1
  200.     END IF
  201.  
  202. SUB newBullet (who, x, y)
  203.     DIM ii AS INTEGER
  204.     FOR ii = 4 TO 100 'find bullet slot
  205.         IF o(ii).live = 0 AND o(ii).exploding = 0 THEN EXIT FOR 'got slot
  206.     NEXT
  207.     IF ii >= 4 AND ii <= 100 THEN
  208.         o(ii).x = x: o(ii).y = y: o(ii).size = 2: o(ii).live = -1: o(who).lastShot = TIMER(.001)
  209.         IF shoot AND who = 0 THEN
  210.             o(ii).dy = -10: o(ii).c = &HFFFFFFFF: bullets = bullets + 1: points = points - 1
  211.             SOUND 700, .3
  212.         ELSEIF who > 0 AND who < 4 THEN
  213.             o(ii).dy = 1: o(ii).c = &HFFFFFF00
  214.             SOUND 300, 1
  215.         END IF
  216.     END IF
  217.     shoot = 0
  218.  
  219. SUB report
  220.     DIM s$
  221.     s$ = "Lives: " + TS$(o(0).live) + "           Bullets: " + TS$(bullets) + "    Hits: " + TS$(hits) + "    Eff% "
  222.     IF bullets = 0 THEN s$ = s$ + "**" ELSE s$ = s$ + TS$(100 * hits \ bullets)
  223.     s$ = s$ + "           Points: " + TS$(points)
  224.     cText xmax / 2, 30, 20, &HFF009900, s$
  225.  
  226. SUB drawRat (i)
  227.     DIM noseX, noseY, neckX, neckY, tailX, tailY, earLX, earLY, earRX, earRY, wX, wY, rh
  228.     rh = _ATAN2(o(i).y - o(i).lastY, o(i).x - o(i).lastX)
  229.     noseX = o(i).x + 2 * o(i).size * COS(rh)
  230.     noseY = o(i).y + 2 * o(i).size * SIN(rh)
  231.     neckX = o(i).x + .75 * o(i).size * COS(rh)
  232.     neckY = o(i).y + .75 * o(i).size * SIN(rh)
  233.     tailX = o(i).x + 2 * o(i).size * COS(rh + _PI)
  234.     tailY = o(i).y + 2 * o(i).size * SIN(rh + _PI)
  235.     earLX = o(i).x + o(i).size * COS(rh - _PI(1 / 12))
  236.     earLY = o(i).y + o(i).size * SIN(rh - _PI(1 / 12))
  237.     earRX = o(i).x + o(i).size * COS(rh + _PI(1 / 12))
  238.     earRY = o(i).y + o(i).size * SIN(rh + _PI(1 / 12))
  239.     fcirc o(i).x, o(i).y, .65 * o(i).size, o(i).c
  240.     fcirc neckX, neckY, o(i).size * .3, o(i).c
  241.     fTri noseX, noseY, earLX, earLY, earRX, earRY, o(i).c
  242.     fcirc earLX, earLY, o(i).size * .3, o(i).c
  243.     fcirc earRX, earRY, o(i).size * .3, o(i).c
  244.     wX = .5 * o(i).size * COS(rh - _PI(11 / 18))
  245.     wY = .5 * o(i).size * SIN(rh - _PI(11 / 18))
  246.     ln noseX + wX, noseY + wY, noseX - wX, noseY - wY, o(i).c
  247.     wX = .5 * o(i).size * COS(rh - _PI(7 / 18))
  248.     wY = .5 * o(i).size * SIN(rh - _PI(7 / 18))
  249.     ln noseX + wX, noseY + wY, noseX - wX, noseY - wY, o(i).c
  250.     ln o(i).x, o(i).y, tailX, tailY, o(i).c
  251.  
  252. SUB drawshooter (x) 'simple red iso triangle pointed towards radianAngle
  253.     DIM y1, y2, x1, x2
  254.     'calculate 3 points of triangle shooter
  255.     y1 = ymax - 10
  256.     y2 = ymax - 60
  257.     x1 = x - 50
  258.     x2 = x + 50
  259.     fTri x, y1, x1, ymax, x, y2, _RGB(0, 0, 200)
  260.     fTri x, y1, x2, ymax, x, y2, _RGB(0, 0, 200)
  261.     ln x, y1, x1, ymax, _RGB32(255, 255, 128)
  262.     ln x1, ymax, x, y2, _RGB32(255, 255, 128)
  263.     ln x, y1, x2, ymax, _RGB32(255, 255, 128)
  264.     ln x2, ymax, x, y2, _RGB32(255, 255, 128)
  265.     ln x, y1, x, y2, _RGB32(255, 255, 128)
  266.  
  267. ' This FUNCTION creates a file in the same folder as your .bas source or .exe
  268. 'EDIT: 2019-07-29 change to FUNCTION to combine Top Ten update functions with Go Again reply.
  269. FUNCTION topTenGoAgain$ (compareScore AS INTEGER)
  270.     DIM fName$, n AS INTEGER, names$(1 TO 10), scores(1 TO 10), name$, score AS INTEGER
  271.     DIM settleScore AS INTEGER, i AS INTEGER
  272.     fName$ = "Top 10 Scores.txt" '<<<  since this is toolbox code change this as needed for app
  273.     CLS: PRINT: PRINT "Your score was:"; compareScore: PRINT: PRINT "Top Ten Scorers and Scores:"
  274.     IF _FILEEXISTS(fName$) THEN
  275.         OPEN fName$ FOR INPUT AS #1
  276.         WHILE EOF(1) = 0 AND n < 10
  277.             n = n + 1
  278.             INPUT #1, name$
  279.             INPUT #1, score
  280.             IF compareScore >= score AND settleScore = 0 THEN
  281.                 PRINT "You have made the Top Ten!"
  282.                 INPUT "Type your name here: ", names$(n)
  283.                 scores(n) = compareScore
  284.                 settleScore = -1
  285.                 n = n + 1
  286.                 IF n <= 10 THEN names$(n) = name$: scores(n) = score
  287.             ELSE
  288.                 scores(n) = score: names$(n) = name$
  289.             END IF
  290.         WEND
  291.         CLOSE #1
  292.         IF n < 10 AND settleScore = 0 THEN
  293.             PRINT "There is a slot open for your name and score."
  294.             INPUT "Type your name here: ", name$
  295.             IF name$ <> "" THEN n = n + 1: names$(n) = name$: scores(n) = compareScore
  296.         END IF
  297.         OPEN fName$ FOR OUTPUT AS #1
  298.         IF n > 10 THEN n = 10
  299.         FOR i = 1 TO n
  300.             PRINT #1, names$(i): PRINT #1, scores(i)
  301.             PRINT i, names$(i), scores(i)
  302.         NEXT
  303.         CLOSE #1
  304.     ELSE
  305.         PRINT "You are first into file!"
  306.         INPUT "Type your name here:"; name$
  307.         OPEN fName$ FOR OUTPUT AS #1
  308.         PRINT #1, name$: PRINT #1, compareScore
  309.         CLOSE #1
  310.     END IF
  311.     PRINT: INPUT "Press <Enter> to play again, <q (or any) + Enter> to quit... "; topTenGoAgain$
  312.  
  313. 'center the text on midpoint x, y
  314. SUB cText (x, y, textHeight, K AS _UNSIGNED LONG, txt$)
  315.     DIM fg AS _UNSIGNED LONG, cur&, I&, mult, xlen
  316.     fg = _DEFAULTCOLOR
  317.     'screen snapshot
  318.     cur& = _DEST
  319.     I& = _NEWIMAGE(8 * LEN(txt$), 16, 32)
  320.     _DEST I&
  321.     COLOR K, _RGBA32(0, 0, 0, 0)
  322.     _PRINTSTRING (0, 0), txt$
  323.     mult = textHeight / 16
  324.     xlen = LEN(txt$) * 8 * mult
  325.     _PUTIMAGE (x - .5 * xlen, y - .5 * textHeight)-STEP(xlen, textHeight), I&, cur&
  326.     COLOR fg
  327.     _FREEIMAGE I&
  328.  
  329.     TS$ = _TRIM$(STR$(n))
  330.  
  331. FUNCTION rand% (lo%, hi%)
  332.     rand% = INT(RND * (hi% - lo% + 1)) + lo%
  333.  
  334. ' 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
  335. SUB fTri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  336.     DIM a&
  337.     a& = _NEWIMAGE(1, 1, 32)
  338.     _DEST a&
  339.     PSET (0, 0), K
  340.     _DEST 0
  341.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  342.     _FREEIMAGE a& '<<< this is important!
  343.  
  344. SUB ln (x1, y1, x2, y2, K AS _UNSIGNED LONG) 'box frame
  345.     LINE (x1, y1)-(x2, y2), K
  346.  
  347. 'from Steve Gold standard
  348. SUB fcirc (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  349.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  350.     DIM X AS INTEGER, Y AS INTEGER
  351.     Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
  352.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  353.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  354.     WHILE X > Y
  355.         RadiusError = RadiusError + Y * 2 + 1
  356.         IF RadiusError >= 0 THEN
  357.             IF X <> Y + 1 THEN
  358.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  359.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  360.             END IF
  361.             X = X - 1
  362.             RadiusError = RadiusError - X * 2
  363.         END IF
  364.         Y = Y + 1
  365.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  366.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  367.     WEND
  368.  

Oh yeah, bullet versus bullet has been added and is working. A rare event but when it happens you will see a white flash and high "metallic" ping! If you have bombs coming your way that you can't escape, try shooting at them.
Title: Re: Invaders bplus style
Post by: SierraKen on July 30, 2019, 02:42:59 pm
Great job! I was thinking about adding multi-shots on mine but the only way I know how to do it would be using an array, like a 10 shot limit on the screen and then start over. But in my game I think it would be too easy. But I like how you added a % of how many times you hit the rat.
Also, the reason why I have a built-in Top Ten is to see if you can beat them, to make it a challenge. :) If you wish to use a built-in Top Ten, feel free to use any of my code. Mine makes the extra file even if you don't have it already, like yours. 
Title: Re: Invaders bplus style
Post by: bplus on July 30, 2019, 03:07:37 pm
Hi Ken,

I already took your Top Ten, modified the heck out of it, in a Sub, and posted code for anyone's Toolbox of Subs and Functions. I have fixed 2 bugs for it and added a new function to it, it returns the user reply about going again. The function and demo are here: https://www.qb64.org/forum/index.php?topic=1511.msg107586#msg107586

Yes, Top Ten is great motivator to challenge people to beat their best performance.

Yes, I am tracking 97 bullets in an array of most all the game objects. Bullets are just like ships and shooters in data you need to track them. My bullets are recycled, they go live when activated and when they go out of bounds or hit a ship, shooter or themselves, they are deactivated, addresses ready to use again somewhere else.

I was going to use hit% as reward for not machine gunning the rats, but what the heck these rats are nuclear toxins and need to be removed before the world is waist deep in their radioactive waste. ;-))
Title: Re: Invaders bplus style
Post by: TempodiBasic on July 30, 2019, 04:13:56 pm
Hi
I find very cool also sound effects. Great
Title: Re: Invaders bplus style
Post by: bplus on July 31, 2019, 08:37:31 am
Thanks TempodiBasic,

Here is a game where Top Ten really works. The sound effects definitely add to playing pleasure too.

Last night I played this game for some time, even seeing bullet versus bullet happen 2 times in a row (when I get tired of sniper shots or get in a jam, I start machine gunning... ) and I am thinking the idea I had for a Boss Pause, a break in intense action, is still good but what I had planned might not work... so don't hold your breath for new versions this one is going on back burner to stew for awhile.

Actually I am considering modifying a Ping Pong and a Breakout version with this style shooter / paddle action.
Title: Re: Invaders bplus style
Post by: Pete on July 31, 2019, 11:31:11 am
Ah, you ratcheted it up another notch! It plays like a real arcade game now. Mice! I mean nice!

Pete
Title: Re: Invaders bplus style
Post by: bplus on July 31, 2019, 11:52:08 am
Ah, you ratcheted it up another notch! It plays like a real arcade game now. Mice! I mean nice!

Pete

The drawings are more mouse than rat. I watched America's Got Talent last night and there was a lady with a rat act. The rat's ears are nothing like the drawing which is pretty Mickey Mouse, I admit. Anyway I am feeling a little remorse for adding to rat's bad rep stereo type, so remember guys these rats/mice are "Maze Refugees" who got into a next door nuclear waste dump and mutated into very dangerous sideways flying aliens with deadly excrement that... well, I guess a backstory is needed for those who might love rats... and might take offense to this game and with all the shootings in the news... wait, that's what the aliens want us to believe, that these are rats or mice! ;-))

BTW Why do they call it "America's Got Talent"? These people are coming from allot of places other than USA. It should be called: The World's Got Talent ( and allot of very unusual people!)
Title: Re: Invaders bplus style
Post by: bplus on July 31, 2019, 09:09:09 pm
Overhauled the Top Ten screen:

Code: QB64: [Select]
  1. _TITLE "Invaders b0_4" 'Bplus started 2019-07-27 inspired by Ken's fun program series
  2.  
  3. ' 2019-07-29 b0_3 from feed back fix game ending with big "Game Over" sign and delay before Top Ten.
  4. ' Show score to compare with Top Ten Numbers.
  5. ' Change the way hits are calculated, use method that avoids distance function or ABS.
  6. ' Change TopTen sub to TopTenGoAgain$ function to also get Play Again reply.
  7. ' OK let's start charging for bullets! 1 point per... and do a hit % to reward skillful shooting
  8. ' change BEEPs to SOUNDS, add more to report, Game Over signals end of game, TopTen does go again also.
  9.  
  10. ' 2019-07-31 Rework the Top Ten screen using Text sub routine that I want to demo in "another one for the Toolbox."
  11. ' This new TopTen function now uses inputBox$ which added a ton of lines to the program!
  12.  
  13.  
  14. CONST xmax = 1200, ymax = 720, PI = 3.141592653589793, PD2 = 1.570796326794897, PT2 = 6.283185307
  15. SCREEN _NEWIMAGE(xmax, ymax, 32)
  16. _SCREENMOVE 100, 20
  17.  
  18. TYPE typeO
  19.     x AS SINGLE
  20.     y AS SINGLE
  21.     xc AS SINGLE
  22.     yc AS SINGLE
  23.     dx AS SINGLE
  24.     dy AS SINGLE
  25.     a AS SINGLE
  26.     lastX AS SINGLE
  27.     lastY AS SINGLE
  28.     v1 AS SINGLE
  29.     v2 AS SINGLE
  30.     size AS SINGLE
  31.     live AS INTEGER
  32.     exploding AS INTEGER
  33.     lastShot AS SINGLE
  34.     c AS _UNSIGNED LONG
  35.  
  36. DIM SHARED o(100) AS typeO, shoot AS INTEGER, points AS INTEGER, bullets AS INTEGER, hits AS INTEGER
  37. DIM i AS INTEGER, j AS INTEGER, kh AS LONG, red AS INTEGER, again$
  38.     setUp
  39.     WHILE o(0).live
  40.         LINE (0, 0)-(xmax, ymax), _RGBA(0, 0, 0, 255), BF
  41.         kh = _KEYHIT
  42.         IF kh = 32 THEN shoot = -1
  43.         IF kh = 18432 THEN o(0).dx = 0
  44.         IF kh = 19200 THEN o(0).dx = -3
  45.         IF kh = 19712 THEN o(0).dx = 3
  46.         report
  47.  
  48.         'dead ships and bullets? but still exploding  this separated out because ships are getting hit more than once while exploding
  49.         FOR i = 1 TO 3
  50.             IF o(i).exploding THEN
  51.                 o(i).exploding = o(i).exploding - 1
  52.                 IF o(i).exploding = 0 THEN
  53.                     newEnemy i
  54.                 ELSE 'draw explosion
  55.                     SOUND 1000 - o(i).size * 3 + (21 - o(i).exploding) * 10, .1
  56.                     red = rand(60, 255)
  57.                     fcirc o(i).x, o(i).y, o(i).exploding * 3, _RGB32(red, rand(0, red), 0)
  58.                 END IF
  59.             END IF 'i = x
  60.         NEXT
  61.         'bullets
  62.         FOR i = 4 TO 100
  63.             IF o(i).exploding THEN
  64.                 o(i).exploding = o(i).exploding - 1
  65.                 SOUND 1600, .05
  66.                 red = rand(60, 255)
  67.                 fcirc o(i).x, o(i).y, o(i).exploding, _RGB32(red, rand(0, red), 0)
  68.             END IF
  69.         NEXT
  70.  
  71.         FOR i = 0 TO 100
  72.             IF o(i).live <> 0 THEN 'draw everything, update positions, check updated position
  73.                 IF i = 0 THEN 'shooter
  74.                     IF o(0).exploding = 0 THEN
  75.                         drawshooter o(i).x
  76.                         IF shoot AND (TIMER(.001) - o(0).lastShot) > .1 THEN '.2 is this the cause of hitting a ship twice?
  77.                             newBullet 0, o(0).x, ymax - 60
  78.                         END IF
  79.                         IF o(i).x + o(i).dx > 0 AND o(i).x + o(i).dx < xmax THEN
  80.                             o(i).x = o(i).x + o(i).dx
  81.                         ELSE
  82.                             o(i).dx = -o(i).dx
  83.                         END IF
  84.                     ELSEIF o(0).exploding THEN 'exploded enough
  85.                         o(i).exploding = o(i).exploding - 1
  86.                         IF o(i).exploding = 0 THEN 'no longer exploding
  87.                             o(0).live = o(0).live - 1
  88.                             IF o(0).live = 0 THEN
  89.                                 fcirc o(0).x, ymax - 75, 50, &HFF770000
  90.                                 report
  91.                                 EXIT FOR
  92.                             ELSE
  93.                                 drawshooter o(i).x
  94.                             END IF
  95.                         ELSE 'exploding
  96.                             SOUND 400 + o(0).exploding * 7, .3
  97.                             red = rand(60, 255)
  98.                             fcirc o(0).x, ymax - 75, o(0).exploding * 6, _RGB32(red, rand(0, red), 0)
  99.                         END IF
  100.                     END IF
  101.  
  102.                 ELSEIF i > 0 AND i < 4 THEN 'enemy ships
  103.                     'update coodinates
  104.                     o(i).lastX = o(i).x: o(i).lastY = o(i).y
  105.                     o(i).x = o(i).xc + 150 * (COS(o(i).a) + COS(o(i).v1 * o(i).a) / 2 + SIN(o(i).v2 * o(i).a) / 3)
  106.                     o(i).y = o(i).yc + 150 * (SIN(o(i).a) + SIN(o(i).v1 * o(i).a) / 2 + COS(o(i).v2 * o(i).a) / 3)
  107.                     drawRat i
  108.                     o(i).a = o(i).a + PI / 1440
  109.                     IF o(i).xc + o(i).dx > 0 AND o(i).xc + o(i).dx < xmax THEN
  110.                         o(i).xc = o(i).xc + o(i).dx
  111.                     ELSE
  112.                         o(i).dx = -o(i).dx
  113.                     END IF
  114.                     'drop bombs
  115.                     IF TIMER(.001) - o(i).lastShot > 3 THEN
  116.                         newBullet i, o(i).x, o(i).y + o(i).size
  117.                     END IF
  118.  
  119.                 ELSEIF i > 3 AND i < 101 THEN 'bullets
  120.                     fcirc o(i).x, o(i).y, o(i).size, o(i).c
  121.                     IF o(i).y + o(i).dy > 0 AND o(i).y + o(i).dy < ymax THEN
  122.                         IF o(i).dy > 0 THEN o(i).dy = o(i).dy + .1 'gravity
  123.                         o(i).y = o(i).y + o(i).dy
  124.                     ELSE
  125.                         o(i).live = 0
  126.                     END IF
  127.  
  128.                     'did this bullet hit anything
  129.                     IF o(i).dy > 0 THEN 'did it hit the shooter
  130.                         IF (o(0).x - o(0).size <= o(i).x) AND (o(i).x <= o(0).x + o(0).size) THEN
  131.                             IF (o(0).y - o(0).size <= o(i).y) AND (o(i).y <= o(0).y + o(0).size + 20) THEN
  132.                                 IF o(0).exploding = 0 AND o(0).live THEN
  133.                                     SOUND 400 + 5 * 20, .1
  134.                                     o(0).exploding = 20 'signal exploding
  135.                                     o(i).live = 0 'kill bullet
  136.                                 END IF
  137.                             END IF
  138.                         END IF
  139.                     ELSEIF o(i).dy < 0 THEN 'did it hit the enemy?
  140.                         FOR j = 1 TO 3
  141.                             IF (o(j).x - o(j).size <= o(i).x) AND (o(i).x <= o(j).x + o(j).size) THEN 'is x right
  142.                                 IF (o(j).y - o(j).size - 5 < o(i).y) AND (o(i).y <= o(j).y + o(j).size + 5) THEN 'is y right
  143.                                     IF o(j).exploding = 0 AND o(j).live <> 0 THEN 'ship not exploding already
  144.                                         o(j).exploding = 20
  145.                                         SOUND 800 - o(i).size * 3, .1
  146.                                         points = points + 50 - o(j).size
  147.                                         hits = hits + 1
  148.                                         o(i).live = 0: o(j).live = 0 'kill bullet and ship
  149.                                     END IF 'if not exploding already
  150.                                 END IF 'if y is right
  151.                             END IF 'if x is right
  152.                         NEXT
  153.  
  154.                         'finally bullet versus bullet!!  remember these bullets (i) are headed up
  155.                         FOR j = i + 1 TO 100 ' find only those going in different directions
  156.                             IF o(j).dy > 0 THEN 'look for bullets headed down
  157.                                 IF o(j).live THEN
  158.                                     IF o(j).x - 3 <= o(i).x AND o(i).x <= o(j).x + 3 THEN 'is x right
  159.                                         IF (o(j).y - 8 <= o(i).y) AND (o(i).y <= o(j).y + o(j).dy) THEN 'is y right  why 16 gravity accums
  160.                                             fcirc o(i).x, o(i).y, 200, &HFFFFFFFF
  161.                                             o(i).live = 0: o(j).live = 0
  162.                                             o(i).exploding = 10
  163.                                             SOUND 2800, 1
  164.                                         END IF 'if y is right
  165.                                     END IF 'if x is right
  166.                                 END IF 'both still live
  167.                             END IF 'bullets going in opposite directions
  168.                         NEXT
  169.                     END IF 'bullet hit
  170.                 END IF 'shooter
  171.             END IF 'live
  172.         NEXT
  173.         _DISPLAY
  174.         _LIMIT 60
  175.     WEND
  176.     cText xmax / 2, ymax / 2, 128, &HFFFF5500, "Game Over"
  177.     _DISPLAY: _DELAY 2.5: _KEYCLEAR ' stop hammer'n the keys!  ;-))
  178.     again$ = topTenGoAgain$(points)
  179. LOOP UNTIL LEN(again$)
  180.  
  181. SUB setUp
  182.     'obj 0 is the player's shooter
  183.     DIM i AS INTEGER
  184.     ERASE o
  185.     points = 0: bullets = 0: hits = 0
  186.     o(0).x = xmax / 2: o(0).y = ymax - 60: o(0).size = 50
  187.     o(0).live = 10
  188.     FOR i = 1 TO 3 'enemy
  189.         newEnemy i
  190.     NEXT
  191.  
  192. SUB newEnemy (i)
  193.     DIM r, g, b
  194.     IF i < 1 OR i > 3 THEN BEEP: EXIT SUB
  195.     o(i).a = RND * PT2: o(i).live = 1: o(i).v1 = rand(2, 19): o(i).v2 = rand(2, 19)
  196.     r = rand(128, 255): g = rand(0, .5 * r): b = rand(0, .5 * g)
  197.     o(i).size = rand(10, 45): o(i).c = _RGB32(r, g, b)
  198.     o(i).yc = ymax / 2 - 30: o(i).lastShot = TIMER(.003) + i
  199.     IF RND < .5 THEN
  200.         o(i).xc = 0: o(i).dx = 1
  201.     ELSE
  202.         o(i).xc = xmax: o(i).dx = -1
  203.     END IF
  204.  
  205. SUB newBullet (who, x, y)
  206.     DIM ii AS INTEGER
  207.     FOR ii = 4 TO 100 'find bullet slot
  208.         IF o(ii).live = 0 AND o(ii).exploding = 0 THEN EXIT FOR 'got slot
  209.     NEXT
  210.     IF ii >= 4 AND ii <= 100 THEN
  211.         o(ii).x = x: o(ii).y = y: o(ii).size = 2: o(ii).live = -1: o(who).lastShot = TIMER(.001)
  212.         IF shoot AND who = 0 THEN
  213.             o(ii).dy = -10: o(ii).c = &HFFFFFFFF: bullets = bullets + 1: points = points - 1
  214.             SOUND 700, .3
  215.         ELSEIF who > 0 AND who < 4 THEN
  216.             o(ii).dy = 1: o(ii).c = &HFFFFFF00
  217.             SOUND 300, 1
  218.         END IF
  219.     END IF
  220.     shoot = 0
  221.  
  222. SUB report
  223.     DIM s$
  224.     s$ = "Lives: " + TS$(o(0).live) + "           Bullets: " + TS$(bullets) + "    Hits: " + TS$(hits) + "    Eff% "
  225.     IF bullets = 0 THEN s$ = s$ + "**" ELSE s$ = s$ + TS$(100 * hits \ bullets)
  226.     s$ = s$ + "           Points: " + TS$(points)
  227.     cText xmax / 2, 30, 20, &HFF009900, s$
  228.  
  229. SUB drawRat (i)
  230.     DIM noseX, noseY, neckX, neckY, tailX, tailY, earLX, earLY, earRX, earRY, wX, wY, rh
  231.     rh = _ATAN2(o(i).y - o(i).lastY, o(i).x - o(i).lastX)
  232.     noseX = o(i).x + 2 * o(i).size * COS(rh)
  233.     noseY = o(i).y + 2 * o(i).size * SIN(rh)
  234.     neckX = o(i).x + .75 * o(i).size * COS(rh)
  235.     neckY = o(i).y + .75 * o(i).size * SIN(rh)
  236.     tailX = o(i).x + 2 * o(i).size * COS(rh + _PI)
  237.     tailY = o(i).y + 2 * o(i).size * SIN(rh + _PI)
  238.     earLX = o(i).x + o(i).size * COS(rh - _PI(1 / 12))
  239.     earLY = o(i).y + o(i).size * SIN(rh - _PI(1 / 12))
  240.     earRX = o(i).x + o(i).size * COS(rh + _PI(1 / 12))
  241.     earRY = o(i).y + o(i).size * SIN(rh + _PI(1 / 12))
  242.     fcirc o(i).x, o(i).y, .65 * o(i).size, o(i).c
  243.     fcirc neckX, neckY, o(i).size * .3, o(i).c
  244.     fTri noseX, noseY, earLX, earLY, earRX, earRY, o(i).c
  245.     fcirc earLX, earLY, o(i).size * .3, o(i).c
  246.     fcirc earRX, earRY, o(i).size * .3, o(i).c
  247.     wX = .5 * o(i).size * COS(rh - _PI(11 / 18))
  248.     wY = .5 * o(i).size * SIN(rh - _PI(11 / 18))
  249.     ln noseX + wX, noseY + wY, noseX - wX, noseY - wY, o(i).c
  250.     wX = .5 * o(i).size * COS(rh - _PI(7 / 18))
  251.     wY = .5 * o(i).size * SIN(rh - _PI(7 / 18))
  252.     ln noseX + wX, noseY + wY, noseX - wX, noseY - wY, o(i).c
  253.     ln o(i).x, o(i).y, tailX, tailY, o(i).c
  254.  
  255. SUB drawshooter (x) 'simple red iso triangle pointed towards radianAngle
  256.     DIM y1, y2, x1, x2
  257.     'calculate 3 points of triangle shooter
  258.     y1 = ymax - 10
  259.     y2 = ymax - 60
  260.     x1 = x - 50
  261.     x2 = x + 50
  262.     fTri x, y1, x1, ymax, x, y2, _RGB(0, 0, 200)
  263.     fTri x, y1, x2, ymax, x, y2, _RGB(0, 0, 200)
  264.     ln x, y1, x1, ymax, _RGB32(255, 255, 128)
  265.     ln x1, ymax, x, y2, _RGB32(255, 255, 128)
  266.     ln x, y1, x2, ymax, _RGB32(255, 255, 128)
  267.     ln x2, ymax, x, y2, _RGB32(255, 255, 128)
  268.     ln x, y1, x, y2, _RGB32(255, 255, 128)
  269.  
  270. ' This FUNCTION creates a file in the same folder as your .bas source or .exe
  271. 'EDIT: 2019-07-31 this function needs:
  272. ' SUB cText(x, y, pixelTextHeight, Colr)
  273. ' SUB inputBox$(prompt$, title$, maxBoxWidth)
  274. ' which needs scnState(restoreTF)
  275. FUNCTION topTenGoAgain$ (compareScore AS INTEGER)
  276.     DIM fName$, n AS INTEGER, names$(1 TO 10), scores(1 TO 10), name$, score AS INTEGER
  277.     DIM settleScore AS INTEGER, i AS INTEGER, yc, s$
  278.  
  279.     fName$ = "Top 10 Scores.txt" '<<<  since this is toolbox code change this as needed for app
  280.     CLS
  281.     cText _WIDTH / 2, _HEIGHT / 8, 20, &HFF0000FF, "Your score was:" + STR$(compareScore)
  282.     IF _FILEEXISTS(fName$) THEN
  283.         OPEN fName$ FOR INPUT AS #1
  284.         WHILE EOF(1) = 0 AND n < 10
  285.             n = n + 1
  286.             INPUT #1, name$
  287.             INPUT #1, score
  288.             IF compareScore >= score AND settleScore = 0 THEN
  289.                 names$(n) = inputBox$("Please enter your name here:", "You have made the Top Ten!", 40)
  290.                 scores(n) = compareScore
  291.                 settleScore = -1
  292.                 n = n + 1
  293.                 IF n <= 10 THEN names$(n) = name$: scores(n) = score
  294.             ELSE
  295.                 scores(n) = score: names$(n) = name$
  296.             END IF
  297.         WEND
  298.         CLOSE #1
  299.         IF n < 10 AND settleScore = 0 THEN
  300.             name$ = inputBox$("Please enter your name here:", "Top Ten has slot open for you:", 40)
  301.             IF name$ <> "" THEN n = n + 1: names$(n) = name$: scores(n) = compareScore
  302.         END IF
  303.         IF n > 10 THEN n = 10
  304.         yc = (_HEIGHT - 20 * (n + 2)) / 2
  305.         cText _WIDTH / 2, yc, 40, &HFFFFFF00, "Top Ten Scorers and Scores:"
  306.         OPEN fName$ FOR OUTPUT AS #1
  307.         FOR i = 1 TO n
  308.             PRINT #1, names$(i): PRINT #1, scores(i)
  309.             s$ = RIGHT$(" " + STR$(i), 2) + "  " + LEFT$(names$(i) + STRING$(25, "."), 20)
  310.             s$ = s$ + RIGHT$(SPACE$(10) + STR$(scores(i)), 10)
  311.             cText _WIDTH / 2, yc + 30 + i * 20, 20, &HFF00FFFF, s$
  312.         NEXT
  313.         _DISPLAY
  314.         _DELAY 3.5
  315.         CLOSE #1
  316.     ELSE
  317.         name$ = inputBox("Please enter your name here:", "You are first into Top Ten file.", 40)
  318.         OPEN fName$ FOR OUTPUT AS #1
  319.         PRINT #1, name$: PRINT #1, compareScore
  320.         CLOSE #1
  321.     END IF
  322.     topTenGoAgain$ = inputBox$("Press <Enter> to play again, enter q (or any) to quit... ", "Play Again?", 66)
  323.  
  324. 'center the text around (x, y) point, needs a graphics screen!
  325. SUB cText (x, y, textHeight, K AS _UNSIGNED LONG, txt$)
  326.     DIM fg AS _UNSIGNED LONG, cur&, I&, mult, xlen
  327.     fg = _DEFAULTCOLOR
  328.     'screen snapshot
  329.     cur& = _DEST
  330.     I& = _NEWIMAGE(8 * LEN(txt$), 16, 32)
  331.     _DEST I&
  332.     COLOR K, _RGBA32(0, 0, 0, 0)
  333.     _PRINTSTRING (0, 0), txt$
  334.     mult = textHeight / 16
  335.     xlen = LEN(txt$) * 8 * mult
  336.     _PUTIMAGE (x - .5 * xlen, y - .5 * textHeight)-STEP(xlen, textHeight), I&, cur&
  337.     COLOR fg
  338.     _FREEIMAGE I&
  339.  
  340. ' You can grab this box by title and drag it around screen for full viewing while answering prompt.
  341. ' Only one line allowed for prompt$
  342. ' boxWidth is 4 more than the allowed length of input, it needs to be longer than title$ and prompt$ also
  343. ' Utilities > Input Box > Input Box 1 tester v 2019-07-31
  344. ' This FUNCTION needs scnState(restroreTF)
  345. FUNCTION inputBox$ (prompt$, title$, boxWidth AS _BYTE)
  346.     DIM ForeColor AS _UNSIGNED LONG, BackColor AS _UNSIGNED LONG, White AS _UNSIGNED LONG
  347.     DIM sw AS INTEGER, sh AS INTEGER, curScrn AS LONG, backScrn AS LONG, ibx AS LONG 'some handles
  348.  
  349.     'colors
  350.     ForeColor = &HFF000055 '<  change as desired  prompt text color, back color or type in area
  351.     BackColor = &HFF6080CC '<  change as desired  used fore color in type in area
  352.     White = &HFFFFFFFF
  353.  
  354.     'items to restore at exit
  355.     scnState 0
  356.  
  357.     'screen snapshot
  358.     sw = _WIDTH: sh = _HEIGHT: curScrn = _DEST
  359.     backScrn = _NEWIMAGE(sw, sh, 32)
  360.     _PUTIMAGE , curScrn, backScrn
  361.  
  362.     'moving box around on screen
  363.     DIM bxW AS INTEGER, bxH AS INTEGER
  364.     DIM mb AS INTEGER, mx AS INTEGER, my AS INTEGER, mi AS INTEGER, grabx AS INTEGER, graby AS INTEGER
  365.     DIM tlx AS INTEGER, tly AS INTEGER 'top left corner of message box
  366.     DIM lastx AS INTEGER, lasty AS INTEGER
  367.     DIM inp$, kh&
  368.  
  369.     'draw message box
  370.     bxW = boxWidth * 8: bxH = 7 * 16
  371.     ibx = _NEWIMAGE(bxW, bxH, 32)
  372.     _DEST ibx
  373.     COLOR &HFF880000, White
  374.     LOCATE 1, 1: PRINT LEFT$(SPACE$(INT((boxWidth - LEN(title$) - 3)) / 2) + title$ + SPACE$(boxWidth), boxWidth)
  375.     COLOR White, &HFFBB0000
  376.     LOCATE 1, boxWidth - 2: PRINT " X "
  377.     COLOR ForeColor, BackColor
  378.     LOCATE 2, 1: PRINT SPACE$(boxWidth);
  379.     LOCATE 3, 1: PRINT LEFT$(SPACE$((boxWidth - LEN(prompt$)) / 2) + prompt$ + SPACE$(boxWidth), boxWidth);
  380.     LOCATE 4, 1: PRINT SPACE$(boxWidth);
  381.     LOCATE 5, 1: PRINT SPACE$(boxWidth);
  382.     LOCATE 6, 1: PRINT SPACE$(boxWidth);
  383.     inp$ = ""
  384.     GOSUB finishBox
  385.  
  386.     'convert to pixels the top left corner of box at moment
  387.     bxW = boxWidth * 8: bxH = 5 * 16
  388.     tlx = (sw - bxW) / 2: tly = (sh - bxH) / 2
  389.     lastx = tlx: lasty = tly
  390.     _KEYCLEAR
  391.     'now allow user to move it around or just read it
  392.     WHILE 1
  393.         CLS
  394.         _PUTIMAGE , backScrn
  395.         _PUTIMAGE (tlx, tly), ibx, curScrn
  396.         _DISPLAY
  397.         WHILE _MOUSEINPUT: WEND
  398.         mx = _MOUSEX: my = _MOUSEY: mb = _MOUSEBUTTON(1)
  399.         IF mb THEN
  400.             IF mx >= tlx AND mx <= tlx + bxW AND my >= tly AND my <= tly + 16 THEN 'mouse down on title bar
  401.                 IF mx >= tlx + bxW - 24 THEN EXIT WHILE
  402.                 grabx = mx - tlx: graby = my - tly
  403.                 DO WHILE mb 'wait for release
  404.                     mi = _MOUSEINPUT: mb = _MOUSEBUTTON(1)
  405.                     mx = _MOUSEX: my = _MOUSEY
  406.                     IF mx - grabx >= 0 AND mx - grabx <= sw - bxW AND my - graby >= 0 AND my - graby <= sh - bxH THEN
  407.                         'attempt to speed up with less updates
  408.                         IF ((lastx - (mx - grabx)) ^ 2 + (lasty - (my - graby)) ^ 2) ^ .5 > 10 THEN
  409.                             tlx = mx - grabx: tly = my - graby
  410.                             CLS
  411.                             _PUTIMAGE , backScrn
  412.                             _PUTIMAGE (tlx, tly), ibx, curScrn
  413.                             lastx = tlx: lasty = tly
  414.                             _DISPLAY
  415.                         END IF
  416.                     END IF
  417.                     _LIMIT 400
  418.                 LOOP
  419.             END IF
  420.         END IF
  421.         kh& = _KEYHIT
  422.         SELECT CASE kh& 'whew not much for the main event!
  423.             CASE 13: EXIT WHILE
  424.             CASE 27: inp$ = "": EXIT WHILE
  425.             CASE 32 TO 128: IF LEN(inp$) < boxWidth - 4 THEN inp$ = inp$ + CHR$(kh&): GOSUB finishBox ELSE BEEP
  426.             CASE 8: IF LEN(inp$) THEN inp$ = LEFT$(inp$, LEN(inp$) - 1): GOSUB finishBox ELSE BEEP
  427.         END SELECT
  428.  
  429.         _LIMIT 60
  430.     WEND
  431.  
  432.     'put things back
  433.     scnState 1 'need fg and bg colors set to cls
  434.     CLS '? is this needed YES!!
  435.     _PUTIMAGE , backScrn
  436.     _DISPLAY
  437.     _FREEIMAGE backScrn
  438.     _FREEIMAGE ibx
  439.     scnState 1 'because we have to call _display, we have to call this again
  440.     inputBox$ = inp$
  441.  
  442.     finishBox:
  443.     _DEST ibx
  444.     COLOR BackColor, ForeColor
  445.     LOCATE 5, 2: PRINT LEFT$(" " + inp$ + SPACE$(boxWidth - 2), boxWidth - 2)
  446.     _DEST curScrn
  447.     RETURN
  448.  
  449. 'from mBox v 2019-07-31 update
  450. ' for saving and restoring screen settins
  451. SUB scnState (restoreTF AS INTEGER) 'Thanks Steve McNeill
  452.     STATIC Font AS LONG, DefaultColor AS _UNSIGNED LONG, BackGroundColor AS _UNSIGNED LONG, Dest AS LONG, Source AS LONG
  453.     STATIC row AS INTEGER, col AS INTEGER, autodisplay AS INTEGER, mb AS INTEGER
  454.     IF restoreTF THEN
  455.         _FONT Font
  456.         COLOR DefaultColor, BackGroundColor
  457.         _DEST Dest
  458.         _SOURCE Source
  459.         LOCATE row, col
  460.         IF autodisplay THEN _AUTODISPLAY ELSE _DISPLAY
  461.         _KEYCLEAR
  462.         WHILE _MOUSEINPUT: WEND 'clear mouse clicks
  463.         mb = _MOUSEBUTTON(1)
  464.         IF mb THEN
  465.             DO
  466.                 WHILE _MOUSEINPUT: WEND
  467.                 mb = _MOUSEBUTTON(1)
  468.                 _LIMIT 100
  469.             LOOP UNTIL mb = 0
  470.         END IF
  471.     ELSE
  472.         Font = _FONT: DefaultColor = _DEFAULTCOLOR: BackGroundColor = _BACKGROUNDCOLOR
  473.         Dest = _DEST: Source = _SOURCE
  474.         row = CSRLIN: col = POS(0): autodisplay = _AUTODISPLAY
  475.     END IF
  476.  
  477.     TS$ = _TRIM$(STR$(n))
  478.  
  479. FUNCTION rand% (lo%, hi%)
  480.     rand% = INT(RND * (hi% - lo% + 1)) + lo%
  481.  
  482. ' 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
  483. SUB fTri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  484.     DIM a&
  485.     a& = _NEWIMAGE(1, 1, 32)
  486.     _DEST a&
  487.     PSET (0, 0), K
  488.     _DEST 0
  489.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  490.     _FREEIMAGE a& '<<< this is important!
  491.  
  492. SUB ln (x1, y1, x2, y2, K AS _UNSIGNED LONG) 'box frame
  493.     LINE (x1, y1)-(x2, y2), K
  494.  
  495. 'from Steve Gold standard
  496. SUB fcirc (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  497.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  498.     DIM X AS INTEGER, Y AS INTEGER
  499.     Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
  500.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  501.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  502.     WHILE X > Y
  503.         RadiusError = RadiusError + Y * 2 + 1
  504.         IF RadiusError >= 0 THEN
  505.             IF X <> Y + 1 THEN
  506.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  507.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  508.             END IF
  509.             X = X - 1
  510.             RadiusError = RadiusError - X * 2
  511.         END IF
  512.         Y = Y + 1
  513.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  514.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  515.     WEND
  516.  
Title: Re: Invaders bplus style
Post by: TempodiBasic on August 01, 2019, 07:44:50 am
Cool Bplus
I have discovered up key that stops shooter and I have experimented  collision bullet to bullet, moreover we can spam bullets shooting aliens.
Great top ten!
Title: Re: Invaders bplus style
Post by: TempodiBasic on August 01, 2019, 08:07:21 am
Sorry Bplus
You have given me a tentation so I have put a little MOD in your cool game.

Code: QB64: [Select]
  1. _TITLE "Invaders b0_4" 'Bplus started 2019-07-27 inspired by Ken's fun program series
  2.  
  3. ' 2019-07-29 b0_3 from feed back fix game ending with big "Game Over" sign and delay before Top Ten.
  4. ' Show score to compare with Top Ten Numbers.
  5. ' Change the way hits are calculated, use method that avoids distance function or ABS.
  6. ' Change TopTen sub to TopTenGoAgain$ function to also get Play Again reply.
  7. ' OK let's start charging for bullets! 1 point per... and do a hit % to reward skillful shooting
  8. ' change BEEPs to SOUNDS, add more to report, Game Over signals end of game, TopTen does go again also.
  9.  
  10. ' 2019-07-31 Rework the Top Ten screen using Text sub routine that I want to demo in "another one for the Toolbox."
  11. ' This new TopTen function now uses inputBox$ which added a ton of lines to the program!
  12.  
  13.  
  14. CONST xmax = 1200, ymax = 720, PI = 3.141592653589793, PD2 = 1.570796326794897, PT2 = 6.283185307
  15. SCREEN _NEWIMAGE(xmax, ymax, 32)
  16. _SCREENMOVE 100, 20
  17.  
  18. TYPE typeO
  19.     x AS SINGLE
  20.     y AS SINGLE
  21.     xc AS SINGLE
  22.     yc AS SINGLE
  23.     dx AS SINGLE
  24.     dy AS SINGLE
  25.     dv AS SINGLE
  26.     a AS SINGLE
  27.     lastX AS SINGLE
  28.     lastY AS SINGLE
  29.     v1 AS SINGLE
  30.     v2 AS SINGLE
  31.     size AS SINGLE
  32.     live AS INTEGER
  33.     exploding AS INTEGER
  34.     lastShot AS SINGLE
  35.     c AS _UNSIGNED LONG
  36.  
  37. DIM SHARED o(100) AS typeO, shoot AS INTEGER, points AS INTEGER, bullets AS INTEGER, hits AS INTEGER
  38. DIM i AS INTEGER, j AS INTEGER, kh AS LONG, red AS INTEGER, again$
  39.     setUp
  40.     WHILE o(0).live
  41.         LINE (0, 0)-(xmax, ymax), _RGBA(0, 0, 0, 255), BF
  42.         kh = _KEYHIT
  43.         IF kh = 32 THEN shoot = -1
  44.         IF kh = 18432 THEN
  45.             o(0).dx = 0: o(0).dv = 0
  46.         END IF
  47.         IF kh = 19200 THEN
  48.             IF o(0).dx <= -3 AND o(0).dx > -7 THEN
  49.                 o(0).dv = o(0).dv - 1
  50.             ELSE
  51.                 o(0).dx = -3
  52.                 o(0).dv = 0
  53.             END IF
  54.         END IF
  55.         IF kh = 19712 THEN
  56.             IF o(0).dx >= 3 AND o(0).dx < 7 THEN
  57.                 o(0).dv = o(0).dv + 1
  58.             ELSE
  59.                 o(0).dx = 3
  60.                 o(0).dv = 0
  61.             END IF
  62.         END IF
  63.  
  64.  
  65.         report
  66.  
  67.         'dead ships and bullets? but still exploding  this separated out because ships are getting hit more than once while exploding
  68.         FOR i = 1 TO 3
  69.             IF o(i).exploding THEN
  70.                 o(i).exploding = o(i).exploding - 1
  71.                 IF o(i).exploding = 0 THEN
  72.                     newEnemy i
  73.                 ELSE 'draw explosion
  74.                     SOUND 1000 - o(i).size * 3 + (21 - o(i).exploding) * 10, .1
  75.                     red = rand(60, 255)
  76.                     fcirc o(i).x, o(i).y, o(i).exploding * 3, _RGB32(red, rand(0, red), 0)
  77.                 END IF
  78.             END IF 'i = x
  79.         NEXT
  80.         'bullets
  81.         FOR i = 4 TO 100
  82.             IF o(i).exploding THEN
  83.                 o(i).exploding = o(i).exploding - 1
  84.                 SOUND 1600, .05
  85.                 red = rand(60, 255)
  86.                 fcirc o(i).x, o(i).y, o(i).exploding, _RGB32(red, rand(0, red), 0)
  87.             END IF
  88.         NEXT
  89.  
  90.         FOR i = 0 TO 100
  91.             IF o(i).live <> 0 THEN 'draw everything, update positions, check updated position
  92.                 IF i = 0 THEN 'shooter
  93.                     IF o(0).exploding = 0 THEN
  94.                         drawshooter o(i).x
  95.                         IF shoot AND (TIMER(.001) - o(0).lastShot) > .1 THEN '.2 is this the cause of hitting a ship twice?
  96.                             newBullet 0, o(0).x, ymax - 60
  97.                         END IF
  98.                         IF o(i).x + o(i).dx + o(i).dv > 0 AND o(i).x + o(i).dx + o(i).dv < xmax THEN
  99.                             o(i).x = o(i).x + o(i).dx + o(i).dv
  100.                         ELSE
  101.                             o(i).dx = -o(i).dx
  102.                             o(i).dv = 0
  103.                         END IF
  104.                     ELSEIF o(0).exploding THEN 'exploded enough
  105.                         o(i).exploding = o(i).exploding - 1
  106.                         IF o(i).exploding = 0 THEN 'no longer exploding
  107.                             o(0).live = o(0).live - 1
  108.                             IF o(0).live = 0 THEN
  109.                                 fcirc o(0).x, ymax - 75, 50, &HFF770000
  110.                                 report
  111.                                 EXIT FOR
  112.                             ELSE
  113.                                 drawshooter o(i).x
  114.                             END IF
  115.                         ELSE 'exploding
  116.                             SOUND 400 + o(0).exploding * 7, .3
  117.                             red = rand(60, 255)
  118.                             fcirc o(0).x, ymax - 75, o(0).exploding * 6, _RGB32(red, rand(0, red), 0)
  119.                         END IF
  120.                     END IF
  121.  
  122.                 ELSEIF i > 0 AND i < 4 THEN 'enemy ships
  123.                     'update coodinates
  124.                     o(i).lastX = o(i).x: o(i).lastY = o(i).y
  125.                     o(i).x = o(i).xc + 150 * (COS(o(i).a) + COS(o(i).v1 * o(i).a) / 2 + SIN(o(i).v2 * o(i).a) / 3)
  126.                     o(i).y = o(i).yc + 150 * (SIN(o(i).a) + SIN(o(i).v1 * o(i).a) / 2 + COS(o(i).v2 * o(i).a) / 3)
  127.                     drawRat i
  128.                     o(i).a = o(i).a + PI / 1440
  129.                     IF o(i).xc + o(i).dx > 0 AND o(i).xc + o(i).dx < xmax THEN
  130.                         o(i).xc = o(i).xc + o(i).dx
  131.                     ELSE
  132.                         o(i).dx = -o(i).dx
  133.                     END IF
  134.                     'drop bombs
  135.                     IF TIMER(.001) - o(i).lastShot > 3 THEN
  136.                         newBullet i, o(i).x, o(i).y + o(i).size
  137.                     END IF
  138.  
  139.                 ELSEIF i > 3 AND i < 101 THEN 'bullets
  140.                     fcirc o(i).x, o(i).y, o(i).size, o(i).c
  141.                     IF o(i).y + o(i).dy > 0 AND o(i).y + o(i).dy < ymax THEN
  142.                         IF o(i).dy > 0 THEN o(i).dy = o(i).dy + .1 'gravity
  143.                         o(i).y = o(i).y + o(i).dy
  144.                     ELSE
  145.                         o(i).live = 0
  146.                     END IF
  147.  
  148.                     'did this bullet hit anything
  149.                     IF o(i).dy > 0 THEN 'did it hit the shooter
  150.                         IF (o(0).x - o(0).size <= o(i).x) AND (o(i).x <= o(0).x + o(0).size) THEN
  151.                             IF (o(0).y - o(0).size <= o(i).y) AND (o(i).y <= o(0).y + o(0).size + 20) THEN
  152.                                 IF o(0).exploding = 0 AND o(0).live THEN
  153.                                     SOUND 400 + 5 * 20, .1
  154.                                     o(0).exploding = 20 'signal exploding
  155.                                     o(i).live = 0 'kill bullet
  156.                                 END IF
  157.                             END IF
  158.                         END IF
  159.                     ELSEIF o(i).dy < 0 THEN 'did it hit the enemy?
  160.                         FOR j = 1 TO 3
  161.                             IF (o(j).x - o(j).size <= o(i).x) AND (o(i).x <= o(j).x + o(j).size) THEN 'is x right
  162.                                 IF (o(j).y - o(j).size - 5 < o(i).y) AND (o(i).y <= o(j).y + o(j).size + 5) THEN 'is y right
  163.                                     IF o(j).exploding = 0 AND o(j).live <> 0 THEN 'ship not exploding already
  164.                                         o(j).exploding = 20
  165.                                         SOUND 800 - o(i).size * 3, .1
  166.                                         points = points + 50 - o(j).size
  167.                                         hits = hits + 1
  168.                                         o(i).live = 0: o(j).live = 0 'kill bullet and ship
  169.                                     END IF 'if not exploding already
  170.                                 END IF 'if y is right
  171.                             END IF 'if x is right
  172.                         NEXT
  173.  
  174.                         'finally bullet versus bullet!!  remember these bullets (i) are headed up
  175.                         FOR j = i + 1 TO 100 ' find only those going in different directions
  176.                             IF o(j).dy > 0 THEN 'look for bullets headed down
  177.                                 IF o(j).live THEN
  178.                                     IF o(j).x - 3 <= o(i).x AND o(i).x <= o(j).x + 3 THEN 'is x right
  179.                                         IF (o(j).y - 8 <= o(i).y) AND (o(i).y <= o(j).y + o(j).dy) THEN 'is y right  why 16 gravity accums
  180.                                             fcirc o(i).x, o(i).y, 200, &HFFFFFFFF
  181.                                             o(i).live = 0: o(j).live = 0
  182.                                             o(i).exploding = 10
  183.                                             SOUND 2800, 1
  184.                                         END IF 'if y is right
  185.                                     END IF 'if x is right
  186.                                 END IF 'both still live
  187.                             END IF 'bullets going in opposite directions
  188.                         NEXT
  189.                     END IF 'bullet hit
  190.                 END IF 'shooter
  191.             END IF 'live
  192.         NEXT
  193.         _DISPLAY
  194.         _LIMIT 60
  195.     WEND
  196.     cText xmax / 2, ymax / 2, 128, &HFFFF5500, "Game Over"
  197.     _DISPLAY: _DELAY 2.5: _KEYCLEAR ' stop hammer'n the keys!  ;-))
  198.     again$ = topTenGoAgain$(points)
  199. LOOP UNTIL LEN(again$)
  200.  
  201. SUB setUp
  202.     'obj 0 is the player's shooter
  203.     DIM i AS INTEGER
  204.     ERASE o
  205.     points = 0: bullets = 0: hits = 0
  206.     o(0).x = xmax / 2: o(0).y = ymax - 60: o(0).size = 50
  207.     o(0).live = 10
  208.     FOR i = 1 TO 3 'enemy
  209.         newEnemy i
  210.     NEXT
  211.  
  212. SUB newEnemy (i)
  213.     DIM r, g, b
  214.     IF i < 1 OR i > 3 THEN BEEP: EXIT SUB
  215.     o(i).a = RND * PT2: o(i).live = 1: o(i).v1 = rand(2, 19): o(i).v2 = rand(2, 19)
  216.     r = rand(128, 255): g = rand(0, .5 * r): b = rand(0, .5 * g)
  217.     o(i).size = rand(10, 45): o(i).c = _RGB32(r, g, b)
  218.     o(i).yc = ymax / 2 - 30: o(i).lastShot = TIMER(.003) + i
  219.     IF RND < .5 THEN
  220.         o(i).xc = 0: o(i).dx = 1
  221.     ELSE
  222.         o(i).xc = xmax: o(i).dx = -1
  223.     END IF
  224.  
  225. SUB newBullet (who, x, y)
  226.     DIM ii AS INTEGER
  227.     FOR ii = 4 TO 100 'find bullet slot
  228.         IF o(ii).live = 0 AND o(ii).exploding = 0 THEN EXIT FOR 'got slot
  229.     NEXT
  230.     IF ii >= 4 AND ii <= 100 THEN
  231.         o(ii).x = x: o(ii).y = y: o(ii).size = 2: o(ii).live = -1: o(who).lastShot = TIMER(.001)
  232.         IF shoot AND who = 0 THEN
  233.             o(ii).dy = -10: o(ii).c = &HFFFFFFFF: bullets = bullets + 1: points = points - 1
  234.             SOUND 700, .3
  235.         ELSEIF who > 0 AND who < 4 THEN
  236.             o(ii).dy = 1: o(ii).c = &HFFFFFF00
  237.             SOUND 300, 1
  238.         END IF
  239.     END IF
  240.     shoot = 0
  241.  
  242. SUB report
  243.     DIM s$
  244.     s$ = "Lives: " + TS$(o(0).live) + "           Bullets: " + TS$(bullets) + "    Hits: " + TS$(hits) + "    Eff% "
  245.     IF bullets = 0 THEN s$ = s$ + "**" ELSE s$ = s$ + TS$(100 * hits \ bullets)
  246.     s$ = s$ + "           Points: " + TS$(points)
  247.     cText xmax / 2, 30, 20, &HFF009900, s$
  248.  
  249. SUB drawRat (i)
  250.     DIM noseX, noseY, neckX, neckY, tailX, tailY, earLX, earLY, earRX, earRY, wX, wY, rh
  251.     rh = _ATAN2(o(i).y - o(i).lastY, o(i).x - o(i).lastX)
  252.     noseX = o(i).x + 2 * o(i).size * COS(rh)
  253.     noseY = o(i).y + 2 * o(i).size * SIN(rh)
  254.     neckX = o(i).x + .75 * o(i).size * COS(rh)
  255.     neckY = o(i).y + .75 * o(i).size * SIN(rh)
  256.     tailX = o(i).x + 2 * o(i).size * COS(rh + _PI)
  257.     tailY = o(i).y + 2 * o(i).size * SIN(rh + _PI)
  258.     earLX = o(i).x + o(i).size * COS(rh - _PI(1 / 12))
  259.     earLY = o(i).y + o(i).size * SIN(rh - _PI(1 / 12))
  260.     earRX = o(i).x + o(i).size * COS(rh + _PI(1 / 12))
  261.     earRY = o(i).y + o(i).size * SIN(rh + _PI(1 / 12))
  262.     fcirc o(i).x, o(i).y, .65 * o(i).size, o(i).c
  263.     fcirc neckX, neckY, o(i).size * .3, o(i).c
  264.     fTri noseX, noseY, earLX, earLY, earRX, earRY, o(i).c
  265.     fcirc earLX, earLY, o(i).size * .3, o(i).c
  266.     fcirc earRX, earRY, o(i).size * .3, o(i).c
  267.     wX = .5 * o(i).size * COS(rh - _PI(11 / 18))
  268.     wY = .5 * o(i).size * SIN(rh - _PI(11 / 18))
  269.     ln noseX + wX, noseY + wY, noseX - wX, noseY - wY, o(i).c
  270.     wX = .5 * o(i).size * COS(rh - _PI(7 / 18))
  271.     wY = .5 * o(i).size * SIN(rh - _PI(7 / 18))
  272.     ln noseX + wX, noseY + wY, noseX - wX, noseY - wY, o(i).c
  273.     ln o(i).x, o(i).y, tailX, tailY, o(i).c
  274.  
  275. SUB drawshooter (x) 'simple red iso triangle pointed towards radianAngle
  276.     DIM y1, y2, x1, x2
  277.     'calculate 3 points of triangle shooter
  278.     y1 = ymax - 10
  279.     y2 = ymax - 60
  280.     x1 = x - 50
  281.     x2 = x + 50
  282.     fTri x, y1, x1, ymax, x, y2, _RGB(0, 0, 200)
  283.     fTri x, y1, x2, ymax, x, y2, _RGB(0, 0, 200)
  284.     ln x, y1, x1, ymax, _RGB32(255, 255, 128)
  285.     ln x1, ymax, x, y2, _RGB32(255, 255, 128)
  286.     ln x, y1, x2, ymax, _RGB32(255, 255, 128)
  287.     ln x2, ymax, x, y2, _RGB32(255, 255, 128)
  288.     ln x, y1, x, y2, _RGB32(255, 255, 128)
  289.  
  290. ' This FUNCTION creates a file in the same folder as your .bas source or .exe
  291. 'EDIT: 2019-07-31 this function needs:
  292. ' SUB cText(x, y, pixelTextHeight, Colr)
  293. ' SUB inputBox$(prompt$, title$, maxBoxWidth)
  294. ' which needs scnState(restoreTF)
  295. FUNCTION topTenGoAgain$ (compareScore AS INTEGER)
  296.     DIM fName$, n AS INTEGER, names$(1 TO 10), scores(1 TO 10), NAME$, score AS INTEGER
  297.     DIM settleScore AS INTEGER, i AS INTEGER, yc, s$
  298.  
  299.     fName$ = "Top 10 Scores.txt" '<<<  since this is toolbox code change this as needed for app
  300.     CLS
  301.     cText _WIDTH / 2, _HEIGHT / 8, 20, &HFF0000FF, "Your score was:" + STR$(compareScore)
  302.     IF _FILEEXISTS(fName$) THEN
  303.         OPEN fName$ FOR INPUT AS #1
  304.         WHILE EOF(1) = 0 AND n < 10
  305.             n = n + 1
  306.             INPUT #1, NAME$
  307.             INPUT #1, score
  308.             IF compareScore >= score AND settleScore = 0 THEN
  309.                 names$(n) = inputBox$("Please enter your name here:", "You have made the Top Ten!", 40)
  310.                 scores(n) = compareScore
  311.                 settleScore = -1
  312.                 n = n + 1
  313.                 IF n <= 10 THEN names$(n) = NAME$: scores(n) = score
  314.             ELSE
  315.                 scores(n) = score: names$(n) = NAME$
  316.             END IF
  317.         WEND
  318.         CLOSE #1
  319.         IF n < 10 AND settleScore = 0 THEN
  320.             NAME$ = inputBox$("Please enter your name here:", "Top Ten has slot open for you:", 40)
  321.             IF NAME$ <> "" THEN n = n + 1: names$(n) = NAME$: scores(n) = compareScore
  322.         END IF
  323.         IF n > 10 THEN n = 10
  324.         yc = (_HEIGHT - 20 * (n + 2)) / 2
  325.         cText _WIDTH / 2, yc, 40, &HFFFFFF00, "Top Ten Scorers and Scores:"
  326.         OPEN fName$ FOR OUTPUT AS #1
  327.         FOR i = 1 TO n
  328.             PRINT #1, names$(i): PRINT #1, scores(i)
  329.             s$ = RIGHT$(" " + STR$(i), 2) + "  " + LEFT$(names$(i) + STRING$(25, "."), 20)
  330.             s$ = s$ + RIGHT$(SPACE$(10) + STR$(scores(i)), 10)
  331.             cText _WIDTH / 2, yc + 30 + i * 20, 20, &HFF00FFFF, s$
  332.         NEXT
  333.         _DISPLAY
  334.         _DELAY 3.5
  335.         CLOSE #1
  336.     ELSE
  337.         NAME$ = inputBox("Please enter your name here:", "You are first into Top Ten file.", 40)
  338.         OPEN fName$ FOR OUTPUT AS #1
  339.         PRINT #1, NAME$: PRINT #1, compareScore
  340.         CLOSE #1
  341.     END IF
  342.     topTenGoAgain$ = inputBox$("Press <Enter> to play again, enter q (or any) to quit... ", "Play Again?", 66)
  343.  
  344. 'center the text around (x, y) point, needs a graphics screen!
  345. SUB cText (x, y, textHeight, K AS _UNSIGNED LONG, txt$)
  346.     DIM fg AS _UNSIGNED LONG, cur&, I&, mult, xlen
  347.     fg = _DEFAULTCOLOR
  348.     'screen snapshot
  349.     cur& = _DEST
  350.     I& = _NEWIMAGE(8 * LEN(txt$), 16, 32)
  351.     _DEST I&
  352.     COLOR K, _RGBA32(0, 0, 0, 0)
  353.     _PRINTSTRING (0, 0), txt$
  354.     mult = textHeight / 16
  355.     xlen = LEN(txt$) * 8 * mult
  356.     _PUTIMAGE (x - .5 * xlen, y - .5 * textHeight)-STEP(xlen, textHeight), I&, cur&
  357.     COLOR fg
  358.     _FREEIMAGE I&
  359.  
  360. ' You can grab this box by title and drag it around screen for full viewing while answering prompt.
  361. ' Only one line allowed for prompt$
  362. ' boxWidth is 4 more than the allowed length of input, it needs to be longer than title$ and prompt$ also
  363. ' Utilities > Input Box > Input Box 1 tester v 2019-07-31
  364. ' This FUNCTION needs scnState(restroreTF)
  365. FUNCTION inputBox$ (prompt$, title$, boxWidth AS _BYTE)
  366.     DIM ForeColor AS _UNSIGNED LONG, BackColor AS _UNSIGNED LONG, White AS _UNSIGNED LONG
  367.     DIM sw AS INTEGER, sh AS INTEGER, curScrn AS LONG, backScrn AS LONG, ibx AS LONG 'some handles
  368.  
  369.     'colors
  370.     ForeColor = &HFF000055 '<  change as desired  prompt text color, back color or type in area
  371.     BackColor = &HFF6080CC '<  change as desired  used fore color in type in area
  372.     White = &HFFFFFFFF
  373.  
  374.     'items to restore at exit
  375.     scnState 0
  376.  
  377.     'screen snapshot
  378.     sw = _WIDTH: sh = _HEIGHT: curScrn = _DEST
  379.     backScrn = _NEWIMAGE(sw, sh, 32)
  380.     _PUTIMAGE , curScrn, backScrn
  381.  
  382.     'moving box around on screen
  383.     DIM bxW AS INTEGER, bxH AS INTEGER
  384.     DIM mb AS INTEGER, mx AS INTEGER, my AS INTEGER, mi AS INTEGER, grabx AS INTEGER, graby AS INTEGER
  385.     DIM tlx AS INTEGER, tly AS INTEGER 'top left corner of message box
  386.     DIM lastx AS INTEGER, lasty AS INTEGER
  387.     DIM INP$, kh&
  388.  
  389.     'draw message box
  390.     bxW = boxWidth * 8: bxH = 7 * 16
  391.     ibx = _NEWIMAGE(bxW, bxH, 32)
  392.     _DEST ibx
  393.     COLOR &HFF880000, White
  394.     LOCATE 1, 1: PRINT LEFT$(SPACE$(INT((boxWidth - LEN(title$) - 3)) / 2) + title$ + SPACE$(boxWidth), boxWidth)
  395.     COLOR White, &HFFBB0000
  396.     LOCATE 1, boxWidth - 2: PRINT " X "
  397.     COLOR ForeColor, BackColor
  398.     LOCATE 2, 1: PRINT SPACE$(boxWidth);
  399.     LOCATE 3, 1: PRINT LEFT$(SPACE$((boxWidth - LEN(prompt$)) / 2) + prompt$ + SPACE$(boxWidth), boxWidth);
  400.     LOCATE 4, 1: PRINT SPACE$(boxWidth);
  401.     LOCATE 5, 1: PRINT SPACE$(boxWidth);
  402.     LOCATE 6, 1: PRINT SPACE$(boxWidth);
  403.     INP$ = ""
  404.     GOSUB finishBox
  405.  
  406.     'convert to pixels the top left corner of box at moment
  407.     bxW = boxWidth * 8: bxH = 5 * 16
  408.     tlx = (sw - bxW) / 2: tly = (sh - bxH) / 2
  409.     lastx = tlx: lasty = tly
  410.     _KEYCLEAR
  411.     'now allow user to move it around or just read it
  412.     WHILE 1
  413.         CLS
  414.         _PUTIMAGE , backScrn
  415.         _PUTIMAGE (tlx, tly), ibx, curScrn
  416.         _DISPLAY
  417.         WHILE _MOUSEINPUT: WEND
  418.         mx = _MOUSEX: my = _MOUSEY: mb = _MOUSEBUTTON(1)
  419.         IF mb THEN
  420.             IF mx >= tlx AND mx <= tlx + bxW AND my >= tly AND my <= tly + 16 THEN 'mouse down on title bar
  421.                 IF mx >= tlx + bxW - 24 THEN EXIT WHILE
  422.                 grabx = mx - tlx: graby = my - tly
  423.                 DO WHILE mb 'wait for release
  424.                     mi = _MOUSEINPUT: mb = _MOUSEBUTTON(1)
  425.                     mx = _MOUSEX: my = _MOUSEY
  426.                     IF mx - grabx >= 0 AND mx - grabx <= sw - bxW AND my - graby >= 0 AND my - graby <= sh - bxH THEN
  427.                         'attempt to speed up with less updates
  428.                         IF ((lastx - (mx - grabx)) ^ 2 + (lasty - (my - graby)) ^ 2) ^ .5 > 10 THEN
  429.                             tlx = mx - grabx: tly = my - graby
  430.                             CLS
  431.                             _PUTIMAGE , backScrn
  432.                             _PUTIMAGE (tlx, tly), ibx, curScrn
  433.                             lastx = tlx: lasty = tly
  434.                             _DISPLAY
  435.                         END IF
  436.                     END IF
  437.                     _LIMIT 400
  438.                 LOOP
  439.             END IF
  440.         END IF
  441.         kh& = _KEYHIT
  442.         SELECT CASE kh& 'whew not much for the main event!
  443.             CASE 13: EXIT WHILE
  444.             CASE 27: INP$ = "": EXIT WHILE
  445.             CASE 32 TO 128: IF LEN(INP$) < boxWidth - 4 THEN INP$ = INP$ + CHR$(kh&): GOSUB finishBox ELSE BEEP
  446.             CASE 8: IF LEN(INP$) THEN INP$ = LEFT$(INP$, LEN(INP$) - 1): GOSUB finishBox ELSE BEEP
  447.         END SELECT
  448.  
  449.         _LIMIT 60
  450.     WEND
  451.  
  452.     'put things back
  453.     scnState 1 'need fg and bg colors set to cls
  454.     CLS '? is this needed YES!!
  455.     _PUTIMAGE , backScrn
  456.     _DISPLAY
  457.     _FREEIMAGE backScrn
  458.     _FREEIMAGE ibx
  459.     scnState 1 'because we have to call _display, we have to call this again
  460.     inputBox$ = INP$
  461.  
  462.     finishBox:
  463.     _DEST ibx
  464.     COLOR BackColor, ForeColor
  465.     LOCATE 5, 2: PRINT LEFT$(" " + INP$ + SPACE$(boxWidth - 2), boxWidth - 2)
  466.     _DEST curScrn
  467.     RETURN
  468.  
  469. 'from mBox v 2019-07-31 update
  470. ' for saving and restoring screen settins
  471. SUB scnState (restoreTF AS INTEGER) 'Thanks Steve McNeill
  472.     STATIC Font AS LONG, DefaultColor AS _UNSIGNED LONG, BackGroundColor AS _UNSIGNED LONG, Dest AS LONG, Source AS LONG
  473.     STATIC row AS INTEGER, col AS INTEGER, autodisplay AS INTEGER, mb AS INTEGER
  474.     IF restoreTF THEN
  475.         _FONT Font
  476.         COLOR DefaultColor, BackGroundColor
  477.         _DEST Dest
  478.         _SOURCE Source
  479.         LOCATE row, col
  480.         IF autodisplay THEN _AUTODISPLAY ELSE _DISPLAY
  481.         _KEYCLEAR
  482.         WHILE _MOUSEINPUT: WEND 'clear mouse clicks
  483.         mb = _MOUSEBUTTON(1)
  484.         IF mb THEN
  485.             DO
  486.                 WHILE _MOUSEINPUT: WEND
  487.                 mb = _MOUSEBUTTON(1)
  488.                 _LIMIT 100
  489.             LOOP UNTIL mb = 0
  490.         END IF
  491.     ELSE
  492.         Font = _FONT: DefaultColor = _DEFAULTCOLOR: BackGroundColor = _BACKGROUNDCOLOR
  493.         Dest = _DEST: Source = _SOURCE
  494.         row = CSRLIN: col = POS(0): autodisplay = _AUTODISPLAY
  495.     END IF
  496.  
  497.     TS$ = _TRIM$(STR$(n))
  498.  
  499. FUNCTION rand% (lo%, hi%)
  500.     rand% = INT(RND * (hi% - lo% + 1)) + lo%
  501.  
  502. ' 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
  503. SUB fTri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  504.     DIM a&
  505.     a& = _NEWIMAGE(1, 1, 32)
  506.     _DEST a&
  507.     PSET (0, 0), K
  508.     _DEST 0
  509.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  510.     _FREEIMAGE a& '<<< this is important!
  511.  
  512. SUB ln (x1, y1, x2, y2, K AS _UNSIGNED LONG) 'box frame
  513.     LINE (x1, y1)-(x2, y2), K
  514.  
  515. 'from Steve Gold standard
  516. SUB fcirc (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  517.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  518.     DIM X AS INTEGER, Y AS INTEGER
  519.     Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
  520.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  521.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  522.     WHILE X > Y
  523.         RadiusError = RadiusError + Y * 2 + 1
  524.         IF RadiusError >= 0 THEN
  525.             IF X <> Y + 1 THEN
  526.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  527.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  528.             END IF
  529.             X = X - 1
  530.             RadiusError = RadiusError - X * 2
  531.         END IF
  532.         Y = Y + 1
  533.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  534.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  535.     WEND
  536.  
  537.  

here is my raw idea of incremental speed for shooter.
Thanks
Title: Re: Invaders bplus style
Post by: bplus on August 01, 2019, 09:25:20 am
Thanks TempodiBasic,

I have thought about allowing a speed increase to shooter but forgot about it when I learned strategies for shooting the aliens and started breaking 1000 regularly.

I don't think we need another .dv variable though. I will play around with this idea, thanks again.

"spamming" the aliens, ha! that's better than "machine gunning" :D

Title: Re: Invaders bplus style
Post by: bplus on August 01, 2019, 10:58:36 am
Hi TempodiBasic,

A .dv is not needed, these changes will work without the .dv added to Type:
Code: QB64: [Select]
  1.         IF kh = 18432 OR kh = 20480 THEN o(0).dx = 0 'up or down, stop for either key (new for down arrow)
  2.  
  3.         'For TempodiBasic acceleration idea
  4.         IF kh = 19200 THEN 'left or more left
  5.             IF o(0).dx < 0 AND o(0).dx > -8 THEN o(0).dx = o(0).dx - 1 ELSE o(0).dx = -3
  6.         END IF
  7.         IF kh = 19712 THEN 'right or more right
  8.             IF o(0).dx > 0 AND o(0).dx < 8 THEN o(0).dx = o(0).dx + 1 ELSE o(0).dx = 3
  9.         END IF
  10.  

I also modified shooter for reporting .dx for testing with acceleration:
Code: QB64: [Select]
  1. SUB drawshooter (x)
  2.     DIM y1, y2, x1, x2
  3.     'calculate 3 points of triangle shooter
  4.     y1 = ymax - 10
  5.     y2 = ymax - 60
  6.     x1 = x - 50
  7.     x2 = x + 50
  8.     fTri x, y1, x1, ymax, x, y2, &HFF0000BB
  9.     fTri x, y1, x2, ymax, x, y2, &HFF0000BB
  10.     ln x, y1, x1, ymax, _RGB32(255, 255, 128)
  11.     ln x1, ymax, x, y2, _RGB32(255, 255, 128)
  12.     ln x, y1, x2, ymax, _RGB32(255, 255, 128)
  13.     ln x2, ymax, x, y2, _RGB32(255, 255, 128)
  14.  
  15.     ' For TempodiBasic Mod this might be handy
  16.     'ln x, y1, x, y2, _RGB32(255, 255, 128)
  17.     COLOR &HFF88BBFF, &HFF0000BB
  18.     _PRINTSTRING (x - 8, y1 - 24), STR$(o(0).dx)
  19.     COLOR &HFFFFFFFF, &HFF000000
  20.  
Title: Re: Invaders bplus style
Post by: TempodiBasic on August 01, 2019, 05:20:12 pm
Hi Bplus

what to say, it is clear that clearer is the code better is the result! ;)

here news
Code: QB64: [Select]
  1. _TITLE "Invaders b0_4_1" 'Bplus started 2019-07-27 inspired by Ken's fun program series
  2.  
  3. ' 2019-07-29 b0_3 from feed back fix game ending with big "Game Over" sign and delay before Top Ten.
  4. ' Show score to compare with Top Ten Numbers.
  5. ' Change the way hits are calculated, use method that avoids distance function or ABS.
  6. ' Change TopTen sub to TopTenGoAgain$ function to also get Play Again reply.
  7. ' OK let's start charging for bullets! 1 point per... and do a hit % to reward skillful shooting
  8. ' change BEEPs to SOUNDS, add more to report, Game Over signals end of game, TopTen does go again also.
  9.  
  10. ' 2019-07-31 Rework the Top Ten screen using Text sub routine that I want to demo in "another one for the Toolbox."
  11. ' This new TopTen function now uses inputBox$ which added a ton of lines to the program!
  12.  
  13. '2019-08-01  incremental speed of shooter
  14.  
  15. CONST xmax = 1200, ymax = 720, PI = 3.141592653589793, PD2 = 1.570796326794897, PT2 = 6.283185307
  16. SCREEN _NEWIMAGE(xmax, ymax, 32)
  17. _SCREENMOVE 100, 20
  18.  
  19. TYPE typeO
  20.     x AS SINGLE
  21.     y AS SINGLE
  22.     xc AS SINGLE
  23.     yc AS SINGLE
  24.     dx AS SINGLE
  25.     dy AS SINGLE
  26.     a AS SINGLE
  27.     lastX AS SINGLE
  28.     lastY AS SINGLE
  29.     v1 AS SINGLE
  30.     v2 AS SINGLE
  31.     size AS SINGLE
  32.     live AS INTEGER
  33.     exploding AS INTEGER
  34.     lastShot AS SINGLE
  35.     c AS _UNSIGNED LONG
  36.  
  37. DIM SHARED o(100) AS typeO, shoot AS INTEGER, points AS INTEGER, bullets AS INTEGER, hits AS INTEGER
  38. DIM i AS INTEGER, j AS INTEGER, kh AS LONG, red AS INTEGER, again$
  39.     setUp
  40.     WHILE o(0).live
  41.         LINE (0, 0)-(xmax, ymax), _RGBA(0, 0, 0, 255), BF
  42.         kh = _KEYHIT
  43.         IF kh = 32 THEN shoot = -1
  44.         'IF kh = 18432 THEN o(0).dx = 0
  45.         ' IF kh = 19200 THEN o(0).dx = -3
  46.         ' IF kh = 19712 THEN o(0).dx = 3
  47.  
  48.         IF kh = 18432 OR kh = 20480 THEN o(0).dx = 0 'up or down, stop for either key (new for down arrow)
  49.  
  50.         'For TempodiBasic acceleration idea
  51.         IF kh = 19200 THEN 'left or more left
  52.             IF o(0).dx < 0 AND o(0).dx > -8 THEN o(0).dx = o(0).dx - 1 ELSE o(0).dx = -3
  53.         END IF
  54.         IF kh = 19712 THEN 'right or more right
  55.             IF o(0).dx > 0 AND o(0).dx < 8 THEN o(0).dx = o(0).dx + 1 ELSE o(0).dx = 3
  56.         END IF
  57.  
  58.         report
  59.  
  60.         'dead ships and bullets? but still exploding  this separated out because ships are getting hit more than once while exploding
  61.         FOR i = 1 TO 3
  62.             IF o(i).exploding THEN
  63.                 o(i).exploding = o(i).exploding - 1
  64.                 IF o(i).exploding = 0 THEN
  65.                     newEnemy i
  66.                 ELSE 'draw explosion
  67.                     SOUND 1000 - o(i).size * 3 + (21 - o(i).exploding) * 10, .1
  68.                     red = rand(60, 255)
  69.                     fcirc o(i).x, o(i).y, o(i).exploding * 3, _RGB32(red, rand(0, red), 0)
  70.                 END IF
  71.             END IF 'i = x
  72.         NEXT
  73.         'bullets
  74.         FOR i = 4 TO 100
  75.             IF o(i).exploding THEN
  76.                 o(i).exploding = o(i).exploding - 1
  77.                 SOUND 1600, .05
  78.                 red = rand(60, 255)
  79.                 fcirc o(i).x, o(i).y, o(i).exploding, _RGB32(red, rand(0, red), 0)
  80.             END IF
  81.         NEXT
  82.  
  83.         FOR i = 0 TO 100
  84.             IF o(i).live <> 0 THEN 'draw everything, update positions, check updated position
  85.                 IF i = 0 THEN 'shooter
  86.                     IF o(0).exploding = 0 THEN
  87.                         drawshooter o(i).x
  88.                         IF shoot AND (TIMER(.001) - o(0).lastShot) > .1 THEN '.2 is this the cause of hitting a ship twice?
  89.                             newBullet 0, o(0).x, ymax - 60
  90.                         END IF
  91.                         IF o(i).x + o(i).dx > 0 AND o(i).x + o(i).dx < xmax THEN
  92.                             o(i).x = o(i).x + o(i).dx
  93.                         ELSE
  94.                             o(i).dx = -o(i).dx
  95.                         END IF
  96.                     ELSEIF o(0).exploding THEN 'exploded enough
  97.                         o(i).exploding = o(i).exploding - 1
  98.                         IF o(i).exploding = 0 THEN 'no longer exploding
  99.                             o(0).live = o(0).live - 1
  100.                             IF o(0).live = 0 THEN
  101.                                 fcirc o(0).x, ymax - 75, 50, &HFF770000
  102.                                 report
  103.                                 EXIT FOR
  104.                             ELSE
  105.                                 drawshooter o(i).x
  106.                             END IF
  107.                         ELSE 'exploding
  108.                             SOUND 400 + o(0).exploding * 7, .3
  109.                             red = rand(60, 255)
  110.                             fcirc o(0).x, ymax - 75, o(0).exploding * 6, _RGB32(red, rand(0, red), 0)
  111.                         END IF
  112.                     END IF
  113.  
  114.                 ELSEIF i > 0 AND i < 4 THEN 'enemy ships
  115.                     'update coodinates
  116.                     o(i).lastX = o(i).x: o(i).lastY = o(i).y
  117.                     o(i).x = o(i).xc + 150 * (COS(o(i).a) + COS(o(i).v1 * o(i).a) / 2 + SIN(o(i).v2 * o(i).a) / 3)
  118.                     o(i).y = o(i).yc + 150 * (SIN(o(i).a) + SIN(o(i).v1 * o(i).a) / 2 + COS(o(i).v2 * o(i).a) / 3)
  119.                     drawRat i
  120.                     o(i).a = o(i).a + PI / 1440
  121.                     IF o(i).xc + o(i).dx > 0 AND o(i).xc + o(i).dx < xmax THEN
  122.                         o(i).xc = o(i).xc + o(i).dx
  123.                     ELSE
  124.                         o(i).dx = -o(i).dx
  125.                     END IF
  126.                     'drop bombs
  127.                     IF TIMER(.001) - o(i).lastShot > 3 THEN
  128.                         newBullet i, o(i).x, o(i).y + o(i).size
  129.                     END IF
  130.  
  131.                 ELSEIF i > 3 AND i < 101 THEN 'bullets
  132.                     fcirc o(i).x, o(i).y, o(i).size, o(i).c
  133.                     IF o(i).y + o(i).dy > 0 AND o(i).y + o(i).dy < ymax THEN
  134.                         IF o(i).dy > 0 THEN o(i).dy = o(i).dy + .1 'gravity
  135.                         o(i).y = o(i).y + o(i).dy
  136.                     ELSE
  137.                         o(i).live = 0
  138.                     END IF
  139.  
  140.                     'did this bullet hit anything
  141.                     IF o(i).dy > 0 THEN 'did it hit the shooter
  142.                         IF (o(0).x - o(0).size <= o(i).x) AND (o(i).x <= o(0).x + o(0).size) THEN
  143.                             IF (o(0).y - o(0).size <= o(i).y) AND (o(i).y <= o(0).y + o(0).size + 20) THEN
  144.                                 IF o(0).exploding = 0 AND o(0).live THEN
  145.                                     SOUND 400 + 5 * 20, .1
  146.                                     o(0).exploding = 20 'signal exploding
  147.                                     o(i).live = 0 'kill bullet
  148.                                 END IF
  149.                             END IF
  150.                         END IF
  151.                     ELSEIF o(i).dy < 0 THEN 'did it hit the enemy?
  152.                         FOR j = 1 TO 3
  153.                             IF (o(j).x - o(j).size <= o(i).x) AND (o(i).x <= o(j).x + o(j).size) THEN 'is x right
  154.                                 IF (o(j).y - o(j).size - 5 < o(i).y) AND (o(i).y <= o(j).y + o(j).size + 5) THEN 'is y right
  155.                                     IF o(j).exploding = 0 AND o(j).live <> 0 THEN 'ship not exploding already
  156.                                         o(j).exploding = 20
  157.                                         SOUND 800 - o(i).size * 3, .1
  158.                                         points = points + 50 - o(j).size
  159.                                         hits = hits + 1
  160.                                         o(i).live = 0: o(j).live = 0 'kill bullet and ship
  161.                                     END IF 'if not exploding already
  162.                                 END IF 'if y is right
  163.                             END IF 'if x is right
  164.                         NEXT
  165.  
  166.                         'finally bullet versus bullet!!  remember these bullets (i) are headed up
  167.                         FOR j = i + 1 TO 100 ' find only those going in different directions
  168.                             IF o(j).dy > 0 THEN 'look for bullets headed down
  169.                                 IF o(j).live THEN
  170.                                     IF o(j).x - 3 <= o(i).x AND o(i).x <= o(j).x + 3 THEN 'is x right
  171.                                         IF (o(j).y - 8 <= o(i).y) AND (o(i).y <= o(j).y + o(j).dy) THEN 'is y right  why 16 gravity accums
  172.                                             fcirc o(i).x, o(i).y, 200, &HFFFFFFFF
  173.                                             o(i).live = 0: o(j).live = 0
  174.                                             o(i).exploding = 10
  175.                                             SOUND 2800, 1
  176.                                         END IF 'if y is right
  177.                                     END IF 'if x is right
  178.                                 END IF 'both still live
  179.                             END IF 'bullets going in opposite directions
  180.                         NEXT
  181.                     END IF 'bullet hit
  182.                 END IF 'shooter
  183.             END IF 'live
  184.         NEXT
  185.         _DISPLAY
  186.         _LIMIT 60
  187.     WEND
  188.     cText xmax / 2, ymax / 2, 128, &HFFFF5500, "Game Over"
  189.     _DISPLAY: _DELAY 2.5: _KEYCLEAR ' stop hammer'n the keys!  ;-))
  190.     again$ = topTenGoAgain$(points)
  191. LOOP UNTIL LEN(again$)
  192.  
  193. SUB setUp
  194.     'obj 0 is the player's shooter
  195.     DIM i AS INTEGER
  196.     ERASE o
  197.     points = 0: bullets = 0: hits = 0
  198.     o(0).x = xmax / 2: o(0).y = ymax - 60: o(0).size = 50
  199.     o(0).live = 10
  200.     FOR i = 1 TO 3 'enemy
  201.         newEnemy i
  202.     NEXT
  203.  
  204. SUB newEnemy (i)
  205.     DIM r, g, b
  206.     IF i < 1 OR i > 3 THEN BEEP: EXIT SUB
  207.     o(i).a = RND * PT2: o(i).live = 1: o(i).v1 = rand(2, 19): o(i).v2 = rand(2, 19)
  208.     r = rand(128, 255): g = rand(0, .5 * r): b = rand(0, .5 * g)
  209.     o(i).size = rand(10, 45): o(i).c = _RGB32(r, g, b)
  210.     o(i).yc = ymax / 2 - 30: o(i).lastShot = TIMER(.003) + i
  211.     IF RND < .5 THEN
  212.         o(i).xc = 0: o(i).dx = 1
  213.     ELSE
  214.         o(i).xc = xmax: o(i).dx = -1
  215.     END IF
  216.  
  217. SUB newBullet (who, x, y)
  218.     DIM ii AS INTEGER
  219.     FOR ii = 4 TO 100 'find bullet slot
  220.         IF o(ii).live = 0 AND o(ii).exploding = 0 THEN EXIT FOR 'got slot
  221.     NEXT
  222.     IF ii >= 4 AND ii <= 100 THEN
  223.         o(ii).x = x: o(ii).y = y: o(ii).size = 2: o(ii).live = -1: o(who).lastShot = TIMER(.001)
  224.         IF shoot AND who = 0 THEN
  225.             o(ii).dy = -10: o(ii).c = &HFFFFFFFF: bullets = bullets + 1: points = points - 1
  226.             SOUND 700, .3
  227.         ELSEIF who > 0 AND who < 4 THEN
  228.             o(ii).dy = 1: o(ii).c = &HFFFFFF00
  229.             SOUND 300, 1
  230.         END IF
  231.     END IF
  232.     shoot = 0
  233.  
  234. SUB report
  235.     DIM s$
  236.     s$ = "Lives: " + TS$(o(0).live) + "           Bullets: " + TS$(bullets) + "    Hits: " + TS$(hits) + "    Eff% "
  237.     IF bullets = 0 THEN s$ = s$ + "**" ELSE s$ = s$ + TS$(100 * hits \ bullets)
  238.     s$ = s$ + "           Points: " + TS$(points)
  239.     cText xmax / 2, 30, 20, &HFF009900, s$
  240.  
  241. SUB drawRat (i)
  242.     DIM noseX, noseY, neckX, neckY, tailX, tailY, earLX, earLY, earRX, earRY, wX, wY, rh
  243.     rh = _ATAN2(o(i).y - o(i).lastY, o(i).x - o(i).lastX)
  244.     noseX = o(i).x + 2 * o(i).size * COS(rh)
  245.     noseY = o(i).y + 2 * o(i).size * SIN(rh)
  246.     neckX = o(i).x + .75 * o(i).size * COS(rh)
  247.     neckY = o(i).y + .75 * o(i).size * SIN(rh)
  248.     tailX = o(i).x + 2 * o(i).size * COS(rh + _PI)
  249.     tailY = o(i).y + 2 * o(i).size * SIN(rh + _PI)
  250.     earLX = o(i).x + o(i).size * COS(rh - _PI(1 / 12))
  251.     earLY = o(i).y + o(i).size * SIN(rh - _PI(1 / 12))
  252.     earRX = o(i).x + o(i).size * COS(rh + _PI(1 / 12))
  253.     earRY = o(i).y + o(i).size * SIN(rh + _PI(1 / 12))
  254.     fcirc o(i).x, o(i).y, .65 * o(i).size, o(i).c
  255.     fcirc neckX, neckY, o(i).size * .3, o(i).c
  256.     fTri noseX, noseY, earLX, earLY, earRX, earRY, o(i).c
  257.     fcirc earLX, earLY, o(i).size * .3, o(i).c
  258.     fcirc earRX, earRY, o(i).size * .3, o(i).c
  259.     wX = .5 * o(i).size * COS(rh - _PI(11 / 18))
  260.     wY = .5 * o(i).size * SIN(rh - _PI(11 / 18))
  261.     ln noseX + wX, noseY + wY, noseX - wX, noseY - wY, o(i).c
  262.     wX = .5 * o(i).size * COS(rh - _PI(7 / 18))
  263.     wY = .5 * o(i).size * SIN(rh - _PI(7 / 18))
  264.     ln noseX + wX, noseY + wY, noseX - wX, noseY - wY, o(i).c
  265.     ln o(i).x, o(i).y, tailX, tailY, o(i).c
  266. SUB drawshooter (x)
  267.     DIM y1, y2, x1, x2
  268.     'calculate 3 points of triangle shooter
  269.     y1 = ymax - 10
  270.     y2 = ymax - 60
  271.     x1 = x - 50
  272.     x2 = x + 50
  273.     fTri x, y1, x1, ymax, x, y2, &HFF0000BB
  274.     fTri x, y1, x2, ymax, x, y2, &HFF0000BB
  275.     ln x, y1, x1, ymax, _RGB32(255, 255, 128)
  276.     ln x1, ymax, x, y2, _RGB32(255, 255, 128)
  277.     ln x, y1, x2, ymax, _RGB32(255, 255, 128)
  278.     ln x2, ymax, x, y2, _RGB32(255, 255, 128)
  279.  
  280.     ' For TempodiBasic Mod this might be handy
  281.     'ln x, y1, x, y2, _RGB32(255, 255, 128)
  282.     COLOR &HFF88BBFF, &HFF0000BB
  283.     _PRINTSTRING (x - 8, y1 - 24), STR$(o(0).dx)
  284.     COLOR &HFFFFFFFF, &HFF000000
  285.  
  286. ' This FUNCTION creates a file in the same folder as your .bas source or .exe
  287. 'EDIT: 2019-07-31 this function needs:
  288. ' SUB cText(x, y, pixelTextHeight, Colr)
  289. ' SUB inputBox$(prompt$, title$, maxBoxWidth)
  290. ' which needs scnState(restoreTF)
  291. FUNCTION topTenGoAgain$ (compareScore AS INTEGER)
  292.     DIM fName$, n AS INTEGER, names$(1 TO 10), scores(1 TO 10), NAME$, score AS INTEGER
  293.     DIM settleScore AS INTEGER, i AS INTEGER, yc, s$
  294.  
  295.     fName$ = "Top 10 Scores.txt" '<<<  since this is toolbox code change this as needed for app
  296.     CLS
  297.     cText _WIDTH / 2, _HEIGHT / 8, 20, &HFF0000FF, "Your score was:" + STR$(compareScore)
  298.     IF _FILEEXISTS(fName$) THEN
  299.         OPEN fName$ FOR INPUT AS #1
  300.         WHILE EOF(1) = 0 AND n < 10
  301.             n = n + 1
  302.             INPUT #1, NAME$
  303.             INPUT #1, score
  304.             IF compareScore >= score AND settleScore = 0 THEN
  305.                 names$(n) = inputBox$("Please enter your name here:", "You have made the Top Ten!", 40)
  306.                 scores(n) = compareScore
  307.                 settleScore = -1
  308.                 n = n + 1
  309.                 IF n <= 10 THEN names$(n) = NAME$: scores(n) = score
  310.             ELSE
  311.                 scores(n) = score: names$(n) = NAME$
  312.             END IF
  313.         WEND
  314.         CLOSE #1
  315.         IF n < 10 AND settleScore = 0 THEN
  316.             NAME$ = inputBox$("Please enter your name here:", "Top Ten has slot open for you:", 40)
  317.             IF NAME$ <> "" THEN n = n + 1: names$(n) = NAME$: scores(n) = compareScore
  318.         END IF
  319.         IF n > 10 THEN n = 10
  320.         yc = (_HEIGHT - 20 * (n + 2)) / 2
  321.         cText _WIDTH / 2, yc, 40, &HFFFFFF00, "Top Ten Scorers and Scores:"
  322.         OPEN fName$ FOR OUTPUT AS #1
  323.         FOR i = 1 TO n
  324.             PRINT #1, names$(i): PRINT #1, scores(i)
  325.             s$ = RIGHT$(" " + STR$(i), 2) + "  " + LEFT$(names$(i) + STRING$(25, "."), 20)
  326.             s$ = s$ + RIGHT$(SPACE$(10) + STR$(scores(i)), 10)
  327.             cText _WIDTH / 2, yc + 30 + i * 20, 20, &HFF00FFFF, s$
  328.         NEXT
  329.         _DISPLAY
  330.         _DELAY 3.5
  331.         CLOSE #1
  332.     ELSE
  333.         NAME$ = inputBox("Please enter your name here:", "You are first into Top Ten file.", 40)
  334.         OPEN fName$ FOR OUTPUT AS #1
  335.         PRINT #1, NAME$: PRINT #1, compareScore
  336.         CLOSE #1
  337.     END IF
  338.     topTenGoAgain$ = inputBox$("Press <Enter> to play again, enter q (or any) to quit... ", "Play Again?", 66)
  339.  
  340. 'center the text around (x, y) point, needs a graphics screen!
  341. SUB cText (x, y, textHeight, K AS _UNSIGNED LONG, txt$)
  342.     DIM fg AS _UNSIGNED LONG, cur&, I&, mult, xlen
  343.     fg = _DEFAULTCOLOR
  344.     'screen snapshot
  345.     cur& = _DEST
  346.     I& = _NEWIMAGE(8 * LEN(txt$), 16, 32)
  347.     _DEST I&
  348.     COLOR K, _RGBA32(0, 0, 0, 0)
  349.     _PRINTSTRING (0, 0), txt$
  350.     mult = textHeight / 16
  351.     xlen = LEN(txt$) * 8 * mult
  352.     _PUTIMAGE (x - .5 * xlen, y - .5 * textHeight)-STEP(xlen, textHeight), I&, cur&
  353.     COLOR fg
  354.     _FREEIMAGE I&
  355.  
  356. ' You can grab this box by title and drag it around screen for full viewing while answering prompt.
  357. ' Only one line allowed for prompt$
  358. ' boxWidth is 4 more than the allowed length of input, it needs to be longer than title$ and prompt$ also
  359. ' Utilities > Input Box > Input Box 1 tester v 2019-07-31
  360. ' This FUNCTION needs scnState(restroreTF)
  361. FUNCTION inputBox$ (prompt$, title$, boxWidth AS _BYTE)
  362.     DIM ForeColor AS _UNSIGNED LONG, BackColor AS _UNSIGNED LONG, White AS _UNSIGNED LONG
  363.     DIM sw AS INTEGER, sh AS INTEGER, curScrn AS LONG, backScrn AS LONG, ibx AS LONG 'some handles
  364.  
  365.     'colors
  366.     ForeColor = &HFF000055 '<  change as desired  prompt text color, back color or type in area
  367.     BackColor = &HFF6080CC '<  change as desired  used fore color in type in area
  368.     White = &HFFFFFFFF
  369.  
  370.     'items to restore at exit
  371.     scnState 0
  372.  
  373.     'screen snapshot
  374.     sw = _WIDTH: sh = _HEIGHT: curScrn = _DEST
  375.     backScrn = _NEWIMAGE(sw, sh, 32)
  376.     _PUTIMAGE , curScrn, backScrn
  377.  
  378.     'moving box around on screen
  379.     DIM bxW AS INTEGER, bxH AS INTEGER
  380.     DIM mb AS INTEGER, mx AS INTEGER, my AS INTEGER, mi AS INTEGER, grabx AS INTEGER, graby AS INTEGER
  381.     DIM tlx AS INTEGER, tly AS INTEGER 'top left corner of message box
  382.     DIM lastx AS INTEGER, lasty AS INTEGER
  383.     DIM INP$, kh&
  384.  
  385.     'draw message box
  386.     bxW = boxWidth * 8: bxH = 7 * 16
  387.     ibx = _NEWIMAGE(bxW, bxH, 32)
  388.     _DEST ibx
  389.     COLOR &HFF880000, White
  390.     LOCATE 1, 1: PRINT LEFT$(SPACE$(INT((boxWidth - LEN(title$) - 3)) / 2) + title$ + SPACE$(boxWidth), boxWidth)
  391.     COLOR White, &HFFBB0000
  392.     LOCATE 1, boxWidth - 2: PRINT " X "
  393.     COLOR ForeColor, BackColor
  394.     LOCATE 2, 1: PRINT SPACE$(boxWidth);
  395.     LOCATE 3, 1: PRINT LEFT$(SPACE$((boxWidth - LEN(prompt$)) / 2) + prompt$ + SPACE$(boxWidth), boxWidth);
  396.     LOCATE 4, 1: PRINT SPACE$(boxWidth);
  397.     LOCATE 5, 1: PRINT SPACE$(boxWidth);
  398.     LOCATE 6, 1: PRINT SPACE$(boxWidth);
  399.     INP$ = ""
  400.     GOSUB finishBox
  401.  
  402.     'convert to pixels the top left corner of box at moment
  403.     bxW = boxWidth * 8: bxH = 5 * 16
  404.     tlx = (sw - bxW) / 2: tly = (sh - bxH) / 2
  405.     lastx = tlx: lasty = tly
  406.     _KEYCLEAR
  407.     'now allow user to move it around or just read it
  408.     WHILE 1
  409.         CLS
  410.         _PUTIMAGE , backScrn
  411.         _PUTIMAGE (tlx, tly), ibx, curScrn
  412.         _DISPLAY
  413.         WHILE _MOUSEINPUT: WEND
  414.         mx = _MOUSEX: my = _MOUSEY: mb = _MOUSEBUTTON(1)
  415.         IF mb THEN
  416.             IF mx >= tlx AND mx <= tlx + bxW AND my >= tly AND my <= tly + 16 THEN 'mouse down on title bar
  417.                 IF mx >= tlx + bxW - 24 THEN EXIT WHILE
  418.                 grabx = mx - tlx: graby = my - tly
  419.                 DO WHILE mb 'wait for release
  420.                     mi = _MOUSEINPUT: mb = _MOUSEBUTTON(1)
  421.                     mx = _MOUSEX: my = _MOUSEY
  422.                     IF mx - grabx >= 0 AND mx - grabx <= sw - bxW AND my - graby >= 0 AND my - graby <= sh - bxH THEN
  423.                         'attempt to speed up with less updates
  424.                         IF ((lastx - (mx - grabx)) ^ 2 + (lasty - (my - graby)) ^ 2) ^ .5 > 10 THEN
  425.                             tlx = mx - grabx: tly = my - graby
  426.                             CLS
  427.                             _PUTIMAGE , backScrn
  428.                             _PUTIMAGE (tlx, tly), ibx, curScrn
  429.                             lastx = tlx: lasty = tly
  430.                             _DISPLAY
  431.                         END IF
  432.                     END IF
  433.                     _LIMIT 400
  434.                 LOOP
  435.             END IF
  436.         END IF
  437.         kh& = _KEYHIT
  438.         SELECT CASE kh& 'whew not much for the main event!
  439.             CASE 13: EXIT WHILE
  440.             CASE 27: INP$ = "": EXIT WHILE
  441.             CASE 32 TO 128: IF LEN(INP$) < boxWidth - 4 THEN INP$ = INP$ + CHR$(kh&): GOSUB finishBox ELSE BEEP
  442.             CASE 8: IF LEN(INP$) THEN INP$ = LEFT$(INP$, LEN(INP$) - 1): GOSUB finishBox ELSE BEEP
  443.         END SELECT
  444.  
  445.         _LIMIT 60
  446.     WEND
  447.  
  448.     'put things back
  449.     scnState 1 'need fg and bg colors set to cls
  450.     CLS '? is this needed YES!!
  451.     _PUTIMAGE , backScrn
  452.     _DISPLAY
  453.     _FREEIMAGE backScrn
  454.     _FREEIMAGE ibx
  455.     scnState 1 'because we have to call _display, we have to call this again
  456.     inputBox$ = INP$
  457.  
  458.     finishBox:
  459.     _DEST ibx
  460.     COLOR BackColor, ForeColor
  461.     LOCATE 5, 2: PRINT LEFT$(" " + INP$ + SPACE$(boxWidth - 2), boxWidth - 2)
  462.     _DEST curScrn
  463.     RETURN
  464.  
  465. 'from mBox v 2019-07-31 update
  466. ' for saving and restoring screen settins
  467. SUB scnState (restoreTF AS INTEGER) 'Thanks Steve McNeill
  468.     STATIC Font AS LONG, DefaultColor AS _UNSIGNED LONG, BackGroundColor AS _UNSIGNED LONG, Dest AS LONG, Source AS LONG
  469.     STATIC row AS INTEGER, col AS INTEGER, autodisplay AS INTEGER, mb AS INTEGER
  470.     IF restoreTF THEN
  471.         _FONT Font
  472.         COLOR DefaultColor, BackGroundColor
  473.         _DEST Dest
  474.         _SOURCE Source
  475.         LOCATE row, col
  476.         IF autodisplay THEN _AUTODISPLAY ELSE _DISPLAY
  477.         _KEYCLEAR
  478.         WHILE _MOUSEINPUT: WEND 'clear mouse clicks
  479.         mb = _MOUSEBUTTON(1)
  480.         IF mb THEN
  481.             DO
  482.                 WHILE _MOUSEINPUT: WEND
  483.                 mb = _MOUSEBUTTON(1)
  484.                 _LIMIT 100
  485.             LOOP UNTIL mb = 0
  486.         END IF
  487.     ELSE
  488.         Font = _FONT: DefaultColor = _DEFAULTCOLOR: BackGroundColor = _BACKGROUNDCOLOR
  489.         Dest = _DEST: Source = _SOURCE
  490.         row = CSRLIN: col = POS(0): autodisplay = _AUTODISPLAY
  491.     END IF
  492.  
  493.     TS$ = _TRIM$(STR$(n))
  494.  
  495. FUNCTION rand% (lo%, hi%)
  496.     rand% = INT(RND * (hi% - lo% + 1)) + lo%
  497.  
  498. ' 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
  499. SUB fTri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  500.     DIM a&
  501.     a& = _NEWIMAGE(1, 1, 32)
  502.     _DEST a&
  503.     PSET (0, 0), K
  504.     _DEST 0
  505.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  506.     _FREEIMAGE a& '<<< this is important!
  507.  
  508. SUB ln (x1, y1, x2, y2, K AS _UNSIGNED LONG) 'box frame
  509.     LINE (x1, y1)-(x2, y2), K
  510.  
  511. 'from Steve Gold standard
  512. SUB fcirc (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  513.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  514.     DIM X AS INTEGER, Y AS INTEGER
  515.     Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
  516.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  517.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  518.     WHILE X > Y
  519.         RadiusError = RadiusError + Y * 2 + 1
  520.         IF RadiusError >= 0 THEN
  521.             IF X <> Y + 1 THEN
  522.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  523.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  524.             END IF
  525.             X = X - 1
  526.             RadiusError = RadiusError - X * 2
  527.         END IF
  528.         Y = Y + 1
  529.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  530.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  531.     WEND
  532.  
  533.  


Title: Re: Invaders bplus style
Post by: bplus on August 01, 2019, 07:45:58 pm
Hi TempodiBasic,

How do you like the accelerator? ha! have you time to play with it?

For me, I got used to the original speed +- 3 and learned tricks for shooting the aliens that look like rat/mice.
And the numbers on the shooter are complete distraction! for me anyway.

But someone who has not practiced with first 3 mods of this code might love the accelerator and numbers report on shooter??? I donno...