Author Topic: Increase array with spacebar? [Solved]  (Read 2296 times)

0 Members and 1 Guest are viewing this topic.

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

Offline 40wattstudio

  • Newbie
  • Posts: 82
    • 40wattstudio
Increase array with spacebar? [Solved]
« on: February 24, 2020, 02:04:59 pm »
Hi everyone!

I'm new to this forum but not to Qbasic. That being said, there's been something that I've been trying to figure out for a while now and haven't made much progress.

Basically, I'm trying to make a traditional top-down shooter where the spacebar is the fire key.
I can make the spacebar fire one unique shot, but what I can't for the life of me figure out is how to get it to fire X amount of *unique* shots. (By unique I mean that each shot has its own Y coordinate so it can be tracked separately for the hit detection).

The way I understand it is like this:
When the player hasn't done anything (like pressed the spacebar to fire a shot), the array used to hold the shots is empty or 0 because nothing has happened. Then when the player presses or holds down the spacebar, the array should increase by 1, generating new coordinates for each unique shot.

Is it possible to start with an empty array and increase by one? Or am I going about this the wrong way entirely?

« Last Edit: February 25, 2020, 07:25:43 pm by 40wattstudio »

FellippeHeitor

  • Guest
Re: Increase array with spacebar?
« Reply #1 on: February 24, 2020, 02:20:33 pm »
Hello 40wattstudio and welcome to the forum.

You're looking for REDIM. You can start an empty array:

Code: QB64: [Select]
  1. REDIM myarray(0) AS LONG

then you can increase it as needed:

Code: QB64: [Select]
  1. REDIM _PRESERVE myarray(UBOUND(myarray) + 1) AS LONG

Beware the the increase/decrease of an array is a memory consuming task, so it's better to increase it by a larger amount, when needed:

Code: QB64: [Select]
  1. REDIM _PRESERVE myarray(UBOUND(myarray) + 100) AS LONG

Maybe you'd be better off with a large array at start, but with an index to track which items have been used, this way you won't have to REDIM it as often.

Click the keywords in the code boxes above to jump the the wiki article on them.

Offline 40wattstudio

  • Newbie
  • Posts: 82
    • 40wattstudio
Re: Increase array with spacebar?
« Reply #2 on: February 24, 2020, 02:46:07 pm »
Hi Fellippe, thanks for the quick response!

I had tried the REDIM before, but that was my very first time using it so I was probably missing something. I definitely don't remember using 2 sets of () in the redimmed array.

It sounds like REDIM can be used inside a subroutine, but can the newly dimensioned array be identified by other subs?
For example, I have  a "hitdetection" sub that needs to cycle through the array of newly generated shots created by the "fireshot" sub.

FellippeHeitor

  • Guest
Re: Increase array with spacebar?
« Reply #3 on: February 24, 2020, 02:54:14 pm »
You can REDIM SHARED in the main module, so the array will be visible across subs and functions.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Increase array with spacebar?
« Reply #4 on: February 24, 2020, 03:10:30 pm »
Hi 40 watts,

You could limit the amount of bullets to nBullets and just track if they are active of not.
When you press spacebar the code scans for nonactive bullet and activates it.
Deactivate bullets as they hit something or leave the screen.

Do you know about TYPE's?

You can setup a Bullet Type and track all you need to know about each

Code: QB64: [Select]
  1. TYPE bullet
  2.     x AS INTEGER
  3.     y AS INTEGER
  4.     dx AS SINGLE 'change along x-axis
  5.     dy AS SINGLE 'change along y axis
  6.     active AS INTEGER ' 0 false, -1 or track how long active
  7.  
  8. Dim shared nBullets = 10  'or make constant
  9.  
  10. DIM SHARED Bullets(1 TO nBullets) AS bullet
  11.  
  12. FOR i = 1 TO nBullets
  13.     'bullets(i).x, bullets(i).y  >>> bullet position  for drawing it
  14.     Bullets(i).x = Bullets(i).x + Bullets(i).dx 'update position on x axis
  15.  
  16.     IF Bullets(i).x < 0 THEN 'bullet off screen deactivate
  17.         Bullets(i).active = 0
  18.     END IF
  19.     'and so on...
  20.  

If all bullets are active when you press spacebar, hear click sound because you just fired a blank ;-))
« Last Edit: February 24, 2020, 03:14:17 pm by bplus »

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
Re: Increase array with spacebar?
« Reply #5 on: February 24, 2020, 03:18:50 pm »
My version - in text mode, for maximal 23 bullets.

Code: QB64: [Select]
  1. 'shoot demo - press spacebar for shoot.
  2.  
  3. TYPE fire
  4.     x AS INTEGER
  5.     y AS INTEGER
  6.  
  7. REDIM fire(1 TO 23) AS fire '23 rows
  8.  
  9. x = _WIDTH / 2
  10. y = 0
  11.  
  12.  
  13.     CLS
  14.     WHILE _KEYDOWN(32)
  15.         s = 1
  16.         DO UNTIL fire(s).y = 0 OR s > 22: s = s + 1: LOOP
  17.         fire(s).y = 1
  18.         EXIT WHILE
  19.     WEND
  20.  
  21.     FOR s = 1 TO 23
  22.         IF fire(s).y THEN
  23.             fire(s).y = fire(s).y + 1
  24.             IF fire(s).y > 23 THEN fire(s).y = 0
  25.             IF fire(s).y THEN LOCATE fire(s).y, x: PRINT "*"
  26.         END IF
  27.     NEXT
  28.     _LIMIT 25
  29.  

Press (and try hold) spacebar.

Offline 40wattstudio

  • Newbie
  • Posts: 82
    • 40wattstudio
Re: Increase array with spacebar?
« Reply #6 on: February 24, 2020, 03:34:01 pm »
Hi bplus and Petr,

Definitely some good suggestions there!

I've been using TYPE's like crazy after I learned how to use them in a School Freeware Qbasic tutorial series.

I'll let you know how it turns out after I get a chance to play around with the code examples.
Thanks!

Marked as best answer by 40wattstudio on February 25, 2020, 02:24:48 pm

Offline TerryRitchie

  • Seasoned Forum Regular
  • Posts: 495
  • Semper Fidelis
Re: Increase array with spacebar?
« Reply #7 on: February 25, 2020, 01:41:35 am »
You don't need to use REDIM to keep track of bullets. Below is a crude demo showing how you can keep track of 5 bullets on the screen. Change the CONST MAXBULLETS = line to 10 or 15 and control more bullets.

Code: QB64: [Select]
  1. CONST FALSE = 0, TRUE = NOT FALSE
  2.  
  3. CONST MAXBULLETS = 5
  4.  
  5. TYPE BULLET
  6.     x AS INTEGER '        X location of bullet
  7.     y AS INTEGER '        Y location of bullet
  8.     active AS _BYTE '     TRUE if bullet currently ascending
  9.  
  10. DIM ShipX AS INTEGER '    X location of ship
  11. DIM shot AS INTEGER '     bullet counter
  12. DIM KeyWait AS INTEGER '  time to wait between shots fired
  13.  
  14. DIM Bullet(MAXBULLETS - 1) AS BULLET ' bullets
  15.  
  16. SCREEN _NEWIMAGE(640, 480, 32) '                                        create window
  17. ShipX = 319 '                                                           X start location of ship (center)
  18.  
  19. DO '                                                                    main loop
  20.     _LIMIT 60 '                                                         60 frames per second
  21.     CLS
  22.     PRINT '                                                             print instructions
  23.     PRINT " RIGHT/LEFT ARROW KEYS TO MOVE"
  24.     PRINT " SPACEBAR TO FIRE"
  25.     PRINT " ESC TO EXIT"
  26.     shot = 0
  27.     DO '                                                                cycle through all 5 bullets
  28.         IF Bullet(shot).active THEN '                                   is this bullet active?
  29.             Bullet(shot).y = Bullet(shot).y - 5 '                       yes, decrement Y location
  30.             IF Bullet(shot).y < 0 THEN '                                leave top of screen?
  31.                 Bullet(shot).active = FALSE '                           yes, this bullet no longer active
  32.             ELSE '                                                      no, bullet still on screen
  33.                 LINE (Bullet(shot).x - 2, Bullet(shot).y)-(Bullet(shot).x + 2, Bullet(shot).y + 4), _RGB32(0, 255, 0), BF
  34.             END IF
  35.         END IF
  36.         shot = shot + 1
  37.     LOOP UNTIL shot = MAXBULLETS
  38.     IF _KEYDOWN(19200) THEN '                                           LEFT ARROW key?
  39.         ShipX = ShipX - 2 '                                             yes, move ship to left
  40.         IF ShipX < 20 THEN ShipX = 20 '                                 stop motion if too far
  41.     END IF
  42.     IF _KEYDOWN(19712) THEN '                                           RIGHT ARROW key?
  43.         ShipX = ShipX + 2 '                                             yes, move ship to right
  44.         IF ShipX > 620 THEN ShipX = 620 '                               stop motion if too far
  45.     END IF
  46.     IF _KEYDOWN(32) AND KeyWait = 0 THEN '                              SPACEBAR pressed and wait timer exhausted?
  47.         shot = 0
  48.         DO '                                                            yes, cycle through all 5 bullets
  49.             IF NOT Bullet(shot).active THEN '                           is this bullet active?
  50.                 Bullet(shot).active = TRUE '                            no, it is now
  51.                 Bullet(shot).x = ShipX '                                set X location of bullet
  52.                 Bullet(shot).y = 453 '                                  set Y location of bullet
  53.                 KeyWait = 5 '                                           wait 5 frames until next shot allowed
  54.                 EXIT DO
  55.             END IF
  56.             shot = shot + 1
  57.         LOOP UNTIL shot = MAXBULLETS
  58.     END IF
  59.     IF KeyWait THEN KeyWait = KeyWait - 1 '                             decrement key wait counter
  60.     LINE (ShipX - 20, 455)-(ShipX + 20, 475), _RGB32(0, 255, 0), BF '   draw ship
  61.     LINE (ShipX - 2, 450)-(ShipX + 2, 454), _RGB32(0, 255, 0), BF '     draw gun stack
  62.     _DISPLAY '                                                          update window with changes
  63. LOOP UNTIL _KEYDOWN(27) '                                               leave when ESC pressed
In order to understand recursion, one must first understand recursion.

Offline MasterGy

  • Seasoned Forum Regular
  • Posts: 327
  • people lie, math never lies
Re: Increase array with spacebar?
« Reply #8 on: February 25, 2020, 03:18:58 am »
I also made a version, I want to show the importance of systematization. be a large array and have lots of indexes, you can give infinite properties to 1 actor later. it is important to say from experience that the way i made the poppy game was that it was easy to add different features per character.

A,D move, SPACE shot

Code: QB64: [Select]
  1. maxballs = 999
  2. DIM balls(maxballs - 1, 5): 'big array, unnecessary save memory, it is worth listing all the characteristics of 1 bullet per index
  3. '0-active
  4. '1-X position
  5. '2-Y position
  6. '3-color
  7. '4-speed
  8. '5-letter-character
  9.  
  10. sc = _NEWIMAGE(640, 480, 32): SCREEN sc
  11.  
  12. meX = 40: meY = 1 'my coordinates
  13. shotspeed_rate = 1 'universal shotspeed rate
  14. randshotspeed = 1 '0=same shot speed 1=different shot speed
  15.  
  16. REM ----------------------------------------------------------------------
  17.  
  18.     IF _KEYDOWN(100) THEN meX = meX + 1 'move left
  19.     IF _KEYDOWN(97) THEN meX = meX - 1 'move right
  20.     IF _KEYDOWN(32) THEN GOSUB createnewshot 'create new shot
  21.  
  22.     IF meX < 1 THEN meX = 1
  23.     IF meX > 79 THEN meX = 80
  24.     GOSUB shotmanager 'calculating balls coordinates
  25.  
  26.     CLS: LOCATE meY, meX: PRINT "X"; 'draw me
  27.     FOR actualindex = 0 TO maxballs - 1 'draw balls
  28.         IF balls(actualindex, 0) THEN 'draw ball ,if active
  29.             LOCATE balls(actualindex, 2), balls(actualindex, 1) 'set coordinates
  30.             COLOR balls(actualindex, 3) 'set color
  31.             PRINT CHR$(balls(actualindex, 5)) 'draw character
  32.         END IF
  33.     NEXT actualindex
  34.  
  35.  
  36. createnewshot:
  37. FOR freeindex = 0 TO maxballs - 1
  38.     IF balls(freeindex, 0) = 0 THEN GOTO findfreeindex
  39. NEXT freeindex: RETURN 'no free index, no new shot
  40. findfreeindex: 'free area index is 'index'
  41. balls(freeindex, 0) = 1 'index is active
  42. balls(freeindex, 1) = meX 'set X position is ME position
  43. balls(freeindex, 2) = 2 'set start Y position
  44. balls(freeindex, 3) = _RGB32(256 * RND, 256 * RND, 256 * RND)
  45. balls(freeindex, 4) = 1 + randshotspeed * RND(1)
  46. balls(freeindex, 5) = 65 + INT(27 * RND(1))
  47.  
  48. shotmanager:
  49. FOR actualindex = 0 TO maxballs - 1
  50.     IF balls(actualindex, 0) THEN 'move shot when activated
  51.         balls(actualindex, 2) = balls(actualindex, 2) + balls(actualindex, 4) * shotspeed_rate 'move ball own speed
  52.         IF balls(actualindex, 2) > 29 THEN balls(actualindex, 0) = 0 'deactived if way end
  53.     END IF
  54. NEXT actualindex
  55.  
  56.  
  57.  
  58.  
  59.  

Offline 40wattstudio

  • Newbie
  • Posts: 82
    • 40wattstudio
Re: Increase array with spacebar?
« Reply #9 on: February 25, 2020, 07:24:27 pm »
Finally got to try out the different sample programs this afternoon. Wow, there sure are a lot of creative ways to do the same basic effect!
Petr: I like the simplicity of yours. Looks very good for Screen 0!
TerryRitchie: Yours was closest to what I needed (having your shots relative to a player ship definitely helped!)
MasterGy: Ah ha! So that's how they make those Matrix screensavers!

Here's what I came up with after I integrated everything:
Code: QB64: [Select]
  1. CONST FALSE = 0, TRUE = NOT FALSE
  2. CONST maxshots = 20
  3.  
  4. TYPE PLAYER
  5.     PIC AS LONG
  6.     HEIGHT AS INTEGER
  7.     MIDX AS INTEGER
  8.     MIDY AS INTEGER
  9.     X AS INTEGER
  10.     Y AS INTEGER
  11.     SPEED AS INTEGER
  12.  
  13.     PIC AS LONG
  14.     HEIGHT AS INTEGER
  15.     COLORS AS INTEGER
  16.     MIDX AS INTEGER
  17.     MIDY AS INTEGER
  18.     TOP AS INTEGER
  19.     BOTTOM AS INTEGER
  20.     RIGHT AS INTEGER
  21.     LEFT AS INTEGER
  22.  
  23. TYPE SHOT
  24.     PIC AS LONG
  25.     HEIGHT AS INTEGER
  26.     MIDX AS INTEGER
  27.     MIDY AS INTEGER
  28.     X AS INTEGER
  29.     Y AS INTEGER
  30.     SPEED AS INTEGER
  31.     ACTIVE AS _BYTE
  32.  
  33. DIM SHARED numshots AS INTEGER
  34. DIM SHARED keydelay AS INTEGER
  35. DIM SHARED shot(maxshots - 1) AS SHOT
  36. DIM SHARED player AS PLAYER
  37.  
  38. '                                                            ==== START HERE ===
  39. newscreen
  40.     IF _KEYDOWN(32) THEN '  - SPACEBAR
  41.  
  42.         basicsettings
  43.         level1
  44.  
  45.     END IF
  46.  
  47. SUB basicsettings '========================================================SUB BASIC SETTINGS
  48.  
  49.     win.MIDX = win.WIDTH / 2
  50.     win.MIDY = win.HEIGHT / 2
  51.     win.TOP = 0
  52.     win.BOTTOM = win.HEIGHT
  53.     win.LEFT = 0
  54.     win.RIGHT = win.WIDTH
  55.  
  56.     player.PIC = _LOADIMAGE("SCRAPSHIP\gfx\playerTEST.png") 'Add path to PNG file here. This is one is 60x60
  57.     player.WIDTH = 60
  58.     player.HEIGHT = 60
  59.     player.MIDX = player.WIDTH / 2
  60.     player.MIDY = player.HEIGHT / 2
  61.     player.X = win.MIDX - player.MIDX
  62.     player.Y = win.MIDY - player.MIDY
  63.     player.SPEED = 2
  64.  
  65.  
  66. SUB level1 '=============================================================SUB LEVEL 1
  67.  
  68.     newscreen
  69.     DO
  70.         PCOPY _DISPLAY, 1
  71.         moveplayer
  72.         fireshot
  73.  
  74.         _DISPLAY
  75.         PCOPY 1, _DISPLAY
  76.     LOOP UNTIL _KEYDOWN(27)
  77.     SYSTEM
  78.  
  79.  
  80. SUB fireshot '======================================================== SUB SET SHOT
  81.  
  82.     numshots = 0
  83.     DO
  84.         IF shot(numshots).ACTIVE THEN
  85.             shot(numshots).PIC = _LOADIMAGE("SCRAPSHIP\gfx\shot.png") 'Add path to PNG file here. This one is 10x20
  86.             shot(numshots).SPEED = 5
  87.             shot(numshots).HEIGHT = 20
  88.             shot(numshots).WIDTH = 10
  89.             shot(numshots).MIDX = shot(numshots).WIDTH / 2
  90.             shot(numshots).MIDY = shot(numshots).HEIGHT / 2
  91.             shot(numshots).Y = shot(numshots).Y - 5
  92.             IF shot(numshots).Y < 0 THEN
  93.                 shot(numshots).ACTIVE = FALSE
  94.             ELSE
  95.                 _PUTIMAGE (shot(numshots).X, shot(numshots).Y), shot(numshots).PIC
  96.             END IF
  97.         END IF
  98.         numshots = numshots + 1
  99.     LOOP UNTIL numshots = maxshots
  100.  
  101.     IF _KEYDOWN(32) AND keydelay = 0 THEN
  102.         numshots = 0
  103.         DO
  104.             IF NOT shot(numshots).ACTIVE THEN
  105.                 shot(numshots).ACTIVE = TRUE
  106.                 shot(numshots).X = player.X + player.MIDX - shot(numshots).MIDX
  107.                 shot(numshots).Y = player.Y
  108.                 keydelay = 10
  109.                 EXIT DO
  110.             END IF
  111.             numshots = numshots + 1
  112.         LOOP UNTIL numshots = maxshots
  113.     END IF
  114.     IF keydelay THEN keydelay = keydelay - 1
  115.  
  116.  
  117. SUB moveplayer '===========================================================SUB MOVE PLAYER
  118.  
  119.     IF _KEYDOWN(CVI(CHR$(0) + "K")) AND player.X > win.LEFT THEN '    - MOVE LEFT
  120.         player.X = player.X - player.SPEED
  121.     END IF
  122.  
  123.     IF _KEYDOWN(CVI(CHR$(0) + "M")) AND player.X + player.WIDTH < win.RIGHT THEN '  - MOVE RIGHT
  124.         player.X = player.X + player.SPEED
  125.     END IF
  126.  
  127.     IF _KEYDOWN(CVI(CHR$(0) + "H")) AND player.Y > win.TOP THEN '  - MOVE UP
  128.         player.Y = player.Y - player.SPEED
  129.     END IF
  130.  
  131.     IF _KEYDOWN(CVI(CHR$(0) + "P")) AND player.Y + player.HEIGHT < win.BOTTOM THEN '   - MOVE DOWN
  132.         player.Y = player.Y + player.SPEED
  133.     END IF
  134.  
  135.     _PUTIMAGE (player.X, player.Y), player.PIC
  136.  
  137.  
  138. SUB newscreen '==============================================================SUB NEW SCREEN
  139.     CLS
  140.     win.WIDTH = 1080
  141.     win.HEIGHT = 1080
  142.     win.COLORS = 32
  143.     SCREEN _NEWIMAGE(win.WIDTH, win.HEIGHT, win.COLORS)
  144.