Author Topic: Help with Starfield  (Read 11898 times)

0 Members and 1 Guest are viewing this topic.

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Help with Starfield
« on: August 09, 2019, 03:10:54 pm »
I've put hours and hours of time in my life to trying to make a starfield over the years. Like the kind that you see in Star Trek or Star Wars with the stars flying toward you.
Once in awhile I dive into it to see if I can think of any new thoughts about it. And what I have here might not ever work. But I'm just wondering about one error message it says. Why does it say "Subscript Out of Range" when have DIMed the variables plenty enough? If any of you know about another Starfield I can learn by, that would be great! I've looked on Google and can't seem to find one although it does say people have made them. Anyway, I'm stuck with this error message for now.
Code: QB64: [Select]
  1. DIM x(2000), y(2000), dx(2000), dy(2000)
  2. SCREEN _NEWIMAGE(800, 600, 32)
  3. st = 1
  4. x(st) = INT(RND * 200) + 300
  5. IF x(st) < 400 THEN dx(st) = -1
  6. IF x(st) > 399 THEN dx(st) = 1
  7. y(st) = INT(RND * 200) + 200
  8. IF y(st) < 300 THEN dy(st) = -1
  9. IF y(st) > 299 THEN dy(st) = 1
  10. go:
  11. a$ = INKEY$
  12. IF a$ = CHR$(27) THEN END
  13. stars = INT(RND * 1000) + 1
  14. IF stars > 999 THEN
  15.     st = st + 1
  16.     IF st > 1000 THEN st = 2
  17.     x(st) = INT(RND * 200) + 300
  18.     IF x(st) < 400 THEN dx(st) = -1
  19.     IF x(st) > 399 THEN dx(st) = 1
  20.     y(st) = INT(RND * 200) + 200
  21.     IF y(st) < 300 THEN dy(st) = -1
  22.     IF y(st) > 299 THEN dy(st) = 1
  23. x(st) = x(st) + dx(st)
  24. y(st) = y(st) + dy(st)
  25. IF x(st) > 800 OR x(st) < 0 OR y(st) > 600 OR y(st) < 0 THEN GOTO go:
  26. LINE (x(st), y(st))-(x(st) + 3, y(st + 3)), rgb32(255, 255, 255), BF
  27. _DELAY .05
  28. LINE (x(st), y(st))-(x(st) + 3, y(st + 3)), rgb32(0, 0, 0), BF
  29. GOTO go:
  30.  

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Help with Starfield
« Reply #1 on: August 09, 2019, 03:26:30 pm »
Actually I just dug one up that someone made from 1996. It has a lot of geometry in it that I won't understand. I'm just looking to make a basic one.
But if you are interested, here it is... I put a _LIMIT command on the loop.

Code: QB64: [Select]
  1. '---------------------------------------------------------------------------
  2.  
  3. '|                            Star Field 1.1                               |
  4.  
  5. '|                A first-person view of flying in space.                  |
  6.  
  7. '|                                                                         |
  8.  
  9. '|                            October 1996                                 |
  10.  
  11. '|                                  by                                     |
  12.  
  13. '|             William Travis Jones  /  wtjones@cswnet.com                 |
  14.  
  15. '|                                                                         |
  16.  
  17. '|                                                                         |
  18.  
  19. '|          Keyboard layout: None, just press a key to quit.               |
  20.  
  21. '|                   Several things are customizable.                      |
  22.  
  23. '|                            Tab Stops: 3                                 |
  24.  
  25. '---------------------------------------------------------------------------
  26.  
  27.  
  28.  
  29. '     As I got more and more hooked on QBASIC, I always wondered how to make
  30.  
  31. 'one of those zooming star animations like the Windows screen savers:
  32.  
  33. '"Flying Windows" and "Flying Through Space". I could study it all
  34.  
  35. 'I wanted, but the fact was I didn't understand how they got the
  36.  
  37. 'values for each of the stars as they moved. I knew that each time through
  38.  
  39. 'the loop, I could: alter the x value, the y value, or both. The screen saver
  40.  
  41. 'went against my current (at the time) knowledge of not just BASIC, but
  42.  
  43. 'programming in general.
  44.  
  45. '     From looking at the screen savers closely, you can easily tell that
  46.  
  47. 'each star(or logo) has a focal point and then moves in a straight line
  48.  
  49. 'outward in each loop.
  50.  
  51. 'The QBASIC LINE statement does the same thing, but wont let you get the
  52.  
  53. 'value of each pixel, which is what I needed.
  54.  
  55. '     I figured the way Microsoft did the screen savers was probably from a
  56.  
  57. 'simple calculation, and that most if not all programs that did similar point
  58.  
  59. 'movement used the same formula. I just needed to find it.
  60.  
  61. '     I posted on comp.sys.lang.basic a request of how to make a point
  62.  
  63. 'rotate around another. Soon after, someone emailed me a small program that
  64.  
  65. 'made a small circle rotate around in another in the center. Thanks Brennen
  66.  
  67. 'Bearnes!
  68.  
  69. '  The source was very easy to understand, except for the
  70.  
  71. 'fact that it uses sine and cosine. I really didn't understand
  72.  
  73. 'what that mean't, and I still don't know to tell you the truth. So
  74.  
  75. 'far I can tell that the program uses sine and cosine to
  76.  
  77. 'emulate the radius of a circle. All I do can pass it: the angle ,x and y
  78.  
  79. 'of the center point(not nesessarily the center of the screen), and the
  80.  
  81. 'radius to get the x and y coordinites of whatever point I need. The
  82.  
  83. 'points in this program are of course the stars. I should stop babbling and
  84.  
  85. 'start with the code...
  86.  
  87. '---------------------------------------------------------------------------
  88.  
  89. '  Update... 1.1 is MUCH faster! It loads the sine and cosine tables into
  90.  
  91. 'memory for a huge speed boost of about 80% or maybe more. I can now make
  92.  
  93. 'all variable integers except I use single precision floating-point
  94.  
  95. 'variables for the tables. I will give Brent P. Newhall credit for the
  96.  
  97. 'table creation code. This version runs uncompiled almost as fast as M/K's
  98.  
  99. 'StarWarp 1.2 in compiled form! (Not trying to be competitive, being theirs
  100.  
  101. 'is in 640*480 and has the stars seem to come from a more distant
  102.  
  103. 'starting point for realism.)
  104.  
  105. '  Each star is reset at or near the middle after reaching a certian radius.
  106.  
  107. 'the downside is that sometimes stars are getting caculated and drawn even
  108.  
  109. 'if they are offscreen. I am working on a version that checks if the stars
  110.  
  111. 'are out of the 320*200 area and then resets them. There are a few problems
  112.  
  113. 'with it, but I will figure it out.
  114.  
  115.  
  116.  
  117. DEFINT A-Z 'now n is not the only integer variable
  118.  
  119. DIM SHARED cosine(0 TO 359) AS SINGLE, sine(0 TO 359) AS SINGLE
  120.  
  121.  
  122.  
  123. PRINT "Creating tables..."
  124.  
  125. FOR n = 0 TO 359
  126.  
  127.     cosine(n) = COS(n * 3.14159 / 180)
  128.  
  129.     sine(n) = SIN(n * 3.14159 / 180)
  130.  
  131.  
  132.  
  133.  
  134. TYPE star 'data type for a star
  135.  
  136.     x AS INTEGER
  137.  
  138.     y AS INTEGER
  139.  
  140.     angle AS INTEGER '360 possible values
  141.  
  142.     radius AS INTEGER 'distance from the center
  143.  
  144.     speed AS INTEGER 'amount of pixels to jump
  145.  
  146.  
  147. CONST tou = 250 'total number of stars on the outer part
  148.  
  149. CONST tin = 50 'total number of stars in the inner part
  150.  
  151. CONST centx = 160, centy = 100
  152.  
  153. CONST true = -1, false = NOT true
  154.  
  155. CONST clrdgry = 8, clrlgry = 7, clrwht = 15 'color constants
  156.  
  157. CONST activepage = 1, visualpage = 0, blankpage = 2
  158.  
  159. DIM outer(1 TO tou) AS star
  160.  
  161. DIM inner(1 TO tin) AS star
  162.  
  163.  
  164. 'these two loops give all the stars starting positions
  165.  
  166. FOR n = 1 TO tou
  167.  
  168.     outer(n).radius = INT(RND * 180) + 30 'at least 30 pixels from center
  169.  
  170.     outer(n).angle = INT(RND * 360)
  171.  
  172.     outer(n).speed = 1
  173.  
  174.  
  175. FOR n = 1 TO tin
  176.  
  177.     inner(n).radius = INT(RND * 200) 'these can start anywhere
  178.  
  179.     inner(n).angle = INT(RND * 360)
  180.  
  181.     inner(n).speed = 1
  182.  
  183.  
  184. '320*200 @ 16 colors - I only use: black, white, and 2 shades of gray
  185.  
  186. SCREEN 7, , workpage, visiblepage 'show one page, but draw on another
  187.  
  188. '******************** {MAIN LOOP} ********************
  189.  
  190.     _LIMIT 50
  191.  
  192.     'calculate the stars with a pi generator
  193.  
  194.     GOSUB doouter
  195.  
  196.     GOSUB doinner
  197.  
  198.     PCOPY blankpage, activepage 'blank out the active page
  199.  
  200.     'draw the stars
  201.  
  202.     GOSUB updateouter
  203.  
  204.     GOSUB updateinner
  205.  
  206.     'LOCATE 12, 16: PRINT "Star Field": LOCATE 22, 17: PRINT "1996 WTJ"
  207.  
  208.     PCOPY activepage, visualpage 'copy the active page to the visual page
  209.  
  210.     SCREEN 7, , activepage, visualpage 'flip it
  211.  
  212.  
  213. '******************** {END MAIN LOOP} ********************
  214.  
  215.  
  216. '******************** {END PROGRAM} **********************
  217.  
  218.  
  219.  
  220. updateouter:
  221.  
  222. FOR n = 1 TO tou
  223.  
  224.     IF outer(n).radius > 75 THEN 'the closer the brighter
  225.  
  226.         PSET (outer(n).x, outer(n).y), clrlgry
  227.  
  228.     ELSE
  229.  
  230.         PSET (outer(n).x, outer(n).y), clrdgry
  231.  
  232.     END IF
  233.  
  234.  
  235.  
  236.  
  237.  
  238. updateinner:
  239.  
  240. FOR n = 1 TO tin
  241.  
  242.     IF inner(n).radius > 80 THEN 'the closer the bigger
  243.  
  244.         LINE (inner(n).x, inner(n).y)-(inner(n).x + 1, inner(n).y + 1), clrwht, B
  245.  
  246.     ELSE
  247.  
  248.         PSET (inner(n).x, inner(n).y), clrwht
  249.  
  250.     END IF
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258. doouter:
  259.  
  260. FOR n = 1 TO tou
  261.  
  262.     IF outer(n).radius > 150 THEN 'put back in center
  263.  
  264.         outer(n).radius = INT(RND * 150) + 30
  265.  
  266.         outer(n).angle = INT(RND * 360)
  267.  
  268.         outer(n).speed = 1
  269.  
  270.     END IF
  271.  
  272.     IF outer(n).radius > 35 THEN outer(n).speed = 2
  273.  
  274.     IF outer(n).radius > 45 THEN outer(n).speed = 4
  275.  
  276.     IF outer(n).radius > 75 THEN outer(n).speed = 6
  277.  
  278.  
  279. FOR n = 1 TO tou
  280.  
  281.     outer(n).radius = outer(n).radius + outer(n).speed
  282.  
  283.     outer(n).x = centx + outer(n).radius * (cosine(outer(n).angle))
  284.  
  285.     outer(n).y = centy - outer(n).radius * (sine(outer(n).angle))
  286.  
  287.  
  288.  
  289.  
  290.  
  291. doinner:
  292.  
  293. FOR n = 1 TO tin
  294.  
  295.     IF inner(n).radius > 150 THEN 'put back in center
  296.  
  297.         inner(n).radius = INT(RND * 40)
  298.  
  299.         inner(n).angle = INT(RND * 360)
  300.  
  301.         inner(n).speed = 3
  302.  
  303.     END IF
  304.  
  305.     IF inner(n).radius > 15 THEN inner(n).speed = 4
  306.  
  307.     IF inner(n).radius > 45 THEN inner(n).speed = 8
  308.  
  309.     IF inner(n).radius > 75 THEN inner(n).speed = 10
  310.  
  311.  
  312. FOR n = 1 TO tin
  313.  
  314.     inner(n).radius = inner(n).radius + inner(n).speed
  315.  
  316.     inner(n).x = centx + inner(n).radius * (cosine(inner(n).angle))
  317.  
  318.     inner(n).y = centy - inner(n).radius * (sine(inner(n).angle))
  319.  
  320.  
  321.  
  322.  

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Help with Starfield
« Reply #2 on: August 09, 2019, 03:29:21 pm »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Help with Starfield
« Reply #3 on: August 09, 2019, 03:31:22 pm »
Hi. Rewrite rgb32 to _RGB32 (row 31, 33)

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Help with Starfield
« Reply #4 on: August 09, 2019, 03:41:19 pm »
LOL Thanks guys! I had a feeling it was a simple mistake on a command. Of course the program still doesn't work but I'll look more into it later and also check out SmMcNeill's link later today. Thanks again.

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: Help with Starfield
« Reply #5 on: August 09, 2019, 06:35:57 pm »
I'm not saying it can't be done without trig (ala sine & cosine), but I would say that it would be much harder without it. Even doing the trig math in the loop, I would expect QB64 to be fast enough that you would have to slow it down with _LIMIT for a pleasing effect. Depending, of course, on how many stars you are plotting.

The geometry of trig is not terribly complex, it just takes some getting used to in order to be comfortable with what it will do for you. The recent tutorial that Steve uploaded is a really good explanation of how it works.

https://www.qb64.org/forum/index.php?topic=1583.msg108049#msg108049

The space vector simulator that I've been working on is not a star field generator but it makes extensive use of sine and cosine functions. I have two library routines that I use:

Code: QB64: [Select]
  1. FUNCTION SinCalc (var1 AS _INTEGER64, var2 AS SINGLE)
  2.  
  3.     'Polar coordinate X finder
  4.     'used to find X coordinate of a speed/distance (var1) and heading/azimuth (var2) in degrees
  5.     SinCalc = var1 * SIN(_D2R(var2))
  6.  
  7. END FUNCTION 'SinCalc
  8.  
  9. FUNCTION CosCalc (var1 AS _INTEGER64, var2 AS SINGLE)
  10.  
  11.     'Polar coordinate Y finder
  12.     'used to find Y coordinate of a speed/distance (var1) and heading/azimuth (var2) in degrees
  13.     CosCalc = var1 * COS(_D2R(var2))
  14.  
  15. END FUNCTION 'CosCalc
  16.  

BTW, var1 in the above examples does not necessarily have to be _INTEGER64, that's just what I need in my particular application as it is working with insanely large kilometer distances.

I set up a WINDOW with x,y that ranges from negative to positive coordinates, like:

    VIEW (1, 1)-(618, 618), background color, border color if any '                  set graphics port square window
    WINDOW (-1000, 1000)-(1000, -1000) '                        set relative cartesian coords 2000x2000 here, but any can be used

at which point the origin 0,0 is at the center of the screen, or you could just use a relative offset value in the calculations if you prefer. Then as you update star positions you just plug in the angle direction and the speed or distance into the functions. Sine gives you your new X position and Cosine gives you your new Y position as the program iterates through your loop.

It's well worth the study, as it can be the basis for drawing all sorts of radial features, compass faces, clock faces, etc.
« Last Edit: August 09, 2019, 07:26:10 pm by OldMoses »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Help with Starfield
« Reply #6 on: August 09, 2019, 09:07:59 pm »
The extended conversation of Starfields was here:
https://www.qb64.org/forum/index.php?topic=1146.msg103395;topicseen#msg103395

And tonight I discover moving through a star field is an awful lot like an explosion, only there is a hole in the middle and all the particles are scattered about the center when they come to view:

Starfield in 50!
Code: QB64: [Select]
  1. _TITLE "Starfield press Up / Down Arrows" '2019-08-09 B+"
  2. 'created from Simple explosion but put "hole" in middle and scatter start locations
  3. SCREEN _NEWIMAGE(720, 720, 32) 'need a graphics screen for graphics
  4. _SCREENMOVE 100, 10 'so bplus can view screen past his tool bar on left
  5. DIM n, p, speed, kh AS LONG
  6. n = 60 'number of stars
  7. DIM SHARED x(n), y(n) 'star location x, y
  8. DIM SHARED dx(n), dy(n) 'traveling in x, y vectors dx, dy (the change in x direction and the change in y direction)
  9.  
  10. FOR p = 0 TO n
  11.     newStar p
  12. speed = 100
  13. WHILE kh <> 27 'while no escape key pressed
  14.     kh = _KEYHIT
  15.     IF kh = 18432 AND speed < 200 THEN speed = speed + 20
  16.     IF kh = 20480 AND speed > 40 THEN speed = speed - 20
  17.     LINE (0, 0)-(_WIDTH, _HEIGHT), _RGBA(0, 0, 0, 30), BF 'only semi black out screen, this effect is so cool!!!!
  18.     FOR p = 0 TO n 'show star by looping through the bunch
  19.         CIRCLE (x(p), y(p)), dx(p)
  20.         IF ABS(dx(p)) >= 1 THEN PAINT (x(p), y(p)), &HFFFFFFFF, &HFFFFFFFF
  21.         'update each star location
  22.         dx(p) = 1.04 * dx(p) 'accel as get closer
  23.         x(p) = x(p) + dx(p) 'change x position
  24.         dy(p) = 1.04 * dy(p) ' increase accel as get closer
  25.         y(p) = y(p) + dy(p) 'change y position
  26.         IF y(p) < -2 OR y(p) > _HEIGHT + 2 THEN newStar p 'replace stars going off screen with new ones
  27.         IF x(p) < -2 OR x(p) > _WIDTH + 2 THEN newStar p
  28.     NEXT
  29.     LOCATE 1, 1: PRINT SPACE$(20)
  30.     LOCATE 1, 1: PRINT "Warp "; speed \ 20
  31.     _DISPLAY 'this so screen wont flicker
  32.     _LIMIT speed 'this needs to go faster than explosion
  33.  
  34. SUB newStar (p)
  35.     DIM d, dist
  36.     'select a random angle = direction to go
  37.     d = 360 * RND 'direction in degrees is a random number from 0 to 360
  38.     dist = 360 * RND + 15 'some distance from around center
  39.     'star location to start
  40.     x(p) = _WIDTH / 2 + dist * COS(_D2R(d))
  41.     y(p) = _HEIGHT / 2 + dist * SIN(_D2R(d))
  42.     'as stars get closer they will speed up so start them all a 1
  43.     'the following calculates the x component of the star vector , the change the star will make along the x axis
  44.     dx(p) = 1 * COS(_D2R(d)) ' _D2R converts our random direction in degrees to radians for COS to process
  45.     'the following calculates the y component of the star vector , the change the star will make along the y axis
  46.     dy(p) = 1 * SIN(_D2R(d)) ' _D2R converts our random direction in degrees to radians for SIN to process
  47.  

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Help with Starfield
« Reply #7 on: August 09, 2019, 09:13:28 pm »
Trigless starfield:

Code: QB64: [Select]
  1.  
  2. TYPE particle
  3.     x AS DOUBLE
  4.     y AS DOUBLE
  5.     vx AS DOUBLE
  6.     vy AS DOUBLE
  7.  
  8. num = 1000
  9. DIM star(num) AS particle
  10.  
  11. FOR k = 1 TO num
  12.     GOSUB makestar
  13.  
  14. dt = .01
  15.     CLS
  16.     FOR k = 1 TO num
  17.         star(k).x = star(k).x + star(k).vx * dt
  18.         star(k).y = star(k).y + star(k).vy * dt
  19.         r2 = star(k).x * star(k).x + star(k).y * star(k).y
  20.         IF (r2 > 400 ^ 2) THEN GOSUB makestar
  21.         PSET (star(k).x + _WIDTH / 2, -star(k).y + _HEIGHT / 2), 15
  22.     NEXT
  23.     _LIMIT 60
  24.     _DISPLAY
  25.  
  26. makestar: 'requires k
  27. star(k).x = (RND - .5) * _WIDTH
  28. star(k).y = (RND - .5) * _HEIGHT
  29. v = 5 + RND * 5
  30. star(k).vx = star(k).x * v
  31. star(k).vy = star(k).y * v
You're not done when it works, you're done when it's right.

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: Help with Starfield
« Reply #8 on: August 09, 2019, 10:34:10 pm »
Trigless starfield:

I think I stand corrected. That's a really cool effect.

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Help with Starfield
« Reply #9 on: August 10, 2019, 12:02:42 am »
Well, nobody's perfect. I've looked at the codes, tried to understand, but haven't learned a lot about many commands like TYPE as well as the math that's above my head. Oh well, at least we got some great starfields from this thread. I will just have to gain more knowledge later on by practicing more. The best I can do is make 1 star move at you at a time. Here is where I got to. And I know why it's not working because my programs are VERY 2 dimensional with my thinking. It's almost like I need a variable inside a variable inside a variable LOL.

Code: QB64: [Select]
  1. _LIMIT 100
  2. SCREEN _NEWIMAGE(800, 600, 32)
  3. GOSUB go3:
  4. go2:
  5. x = x + dx
  6. y = y + dy
  7. IF x > 799 OR x < 0 OR y > 599 OR y < 0 THEN GOSUB go3:
  8. FOR s = .25 TO 3 STEP .25
  9.     CIRCLE (x, y), s, _RGB32(255, 255, 255)
  10. _DELAY .01
  11. FOR s = .25 TO 3 STEP .25
  12.     CIRCLE (x, y), s, _RGB32(0, 0, 0)
  13. t = t + 1
  14. IF t > 500 THEN GOSUB go3:
  15. GOTO go2:
  16.  
  17. go3:
  18. t = 0
  19. x = INT(RND * 300) + 200
  20. y = INT(RND * 200) + 200
  21. IF x > 400 THEN dx = 1
  22. IF x < 401 THEN dx = -1
  23. IF y > 300 THEN dy = 1
  24. IF y < 299 THEN dy = -1
  25.  
  26.  


Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Help with Starfield
« Reply #10 on: August 10, 2019, 12:39:14 am »
Well here is STxAxTIC's code without TYPE and on a proper screen to do the cool effect:
Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(500, 500, 32)
  2.  
  3. num = 1000
  4.  
  5. DIM x(num), y(num), dx(num), dy(num)
  6. FOR k = 1 TO num
  7.     GOSUB makestar
  8.  
  9. dt = .01
  10.     LINE (0, 0)-(_WIDTH, _HEIGHT), _RGBA32(0, 0, 0, 30), BF
  11.     FOR k = 1 TO num
  12.         x(k) = x(k) + dx(k) * dt
  13.         y(k) = y(k) + dy(k) * dt
  14.         r2 = x(k) * x(k) + y(k) * y(k)
  15.         IF (r2 > 400 ^ 2) THEN GOSUB makestar
  16.         PSET (x(k) + _WIDTH / 2, -y(k) + _HEIGHT / 2), _RGB32(255, 255, 255)
  17.     NEXT
  18.     _LIMIT 60
  19.     _DISPLAY
  20.  
  21. makestar: 'requires k
  22. x(k) = (RND - .5) * _WIDTH
  23. y(k) = (RND - .5) * _HEIGHT
  24. v = 5 + RND * 5
  25. dx(k) = x(k) * v
  26. dy(k) = y(k) * v
  27.  
  28.  

So no Trig and no TYPE but he likes to graph things / locate things as offset from screen center and the r2 thing is about seeing if stars are 400 pixels away from center or out of bounds and time for a new Star.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Help with Starfield
« Reply #11 on: August 10, 2019, 01:33:39 am »
Well, nobody's perfect. I've looked at the codes, tried to understand, but haven't learned a lot about many commands like TYPE as well as the math that's above my head. Oh well, at least we got some great starfields from this thread. I will just have to gain more knowledge later on by practicing more. The best I can do is make 1 star move at you at a time. Here is where I got to. And I know why it's not working because my programs are VERY 2 dimensional with my thinking. It's almost like I need a variable inside a variable inside a variable LOL.

Code: QB64: [Select]
  1. _LIMIT 100
  2. SCREEN _NEWIMAGE(800, 600, 32)
  3. GOSUB go3:
  4. go2:
  5. x = x + dx
  6. y = y + dy
  7. IF x > 799 OR x < 0 OR y > 599 OR y < 0 THEN GOSUB go3:
  8. FOR s = .25 TO 3 STEP .25
  9.     CIRCLE (x, y), s, _RGB32(255, 255, 255)
  10. _DELAY .01
  11. FOR s = .25 TO 3 STEP .25
  12.     CIRCLE (x, y), s, _RGB32(0, 0, 0)
  13. t = t + 1
  14. IF t > 500 THEN GOSUB go3:
  15. GOTO go2:
  16.  
  17. go3:
  18. t = 0
  19. x = INT(RND * 300) + 200
  20. y = INT(RND * 200) + 200
  21. IF x > 400 THEN dx = 1
  22. IF x < 401 THEN dx = -1
  23. IF y > 300 THEN dy = 1
  24. IF y < 299 THEN dy = -1
  25.  
  26.  

Before working with whole screen of moving circles, study this for basic structure of animating, get one moving circle going, the rest will be way easier:

Code: QB64: [Select]
  1. _TITLE "BASIC Animation 101: Drawing a moving circle"
  2. SCREEN _NEWIMAGE(500, 500, 32)
  3.  
  4. 'initialize variables
  5. GOSUB newCircle
  6.  
  7. 'setup main loop
  8.  
  9.     CLS 'each loop around start by erasing everything
  10.  
  11.  
  12.     'now draw all your objects at their x, y location
  13.  
  14.     'here is a call to the sub circle fill
  15.     circleFill x, y, 10, _RGB32(0, 0, 255)
  16.  
  17.     'calculate the new location for everything
  18.     x = x + dx
  19.     y = y + dy
  20.  
  21.     'are we still inside the screen for everything?
  22.     IF x < 0 OR x > _WIDTH THEN GOSUB newCircle
  23.     IF y < 0 OR y > _HEIGHT THEN GOSUB newCircle
  24.  
  25.  
  26.     _DISPLAY ' stop flicker from  cls
  27.  
  28.     _LIMIT 60 'slow this sucker down so humans can see the action
  29.  
  30. LOOP UNTIL _KEYHIT = 27 'setup an exit
  31.  
  32. END 'dont let program execution go beyond this point
  33.  
  34. newCircle:
  35. x = RND * _WIDTH * 5 + _WIDTH * .25
  36. y = RND * _HEIGHT * 5 + _WIDTH * .25
  37. dx = RND * 10 - 5
  38. dy = RND * 10 - 5
  39.  
  40. ' this is very handy if circles don't overlap
  41. SUB circleFill (x, y, r, colr AS _UNSIGNED LONG)
  42.     CIRCLE (x, y), r, colr
  43.     IF r >= 1 THEN PAINT (x, y), colr, colr
  44.  
  45.  

EDIT: added radius check before painting for circleFill
« Last Edit: August 10, 2019, 07:32:58 am by bplus »

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: Help with Starfield
« Reply #12 on: August 10, 2019, 07:36:21 am »
Here's one that doesn't use "much" trig, other than a reference to the Pythagorean theorem. Frankly, I'm a little surprised it worked.

It uses a 3D "space" to acheive an apparent movement effect, with more distant stars moving more slowly past the user's POV. Then scales it to a viewport ahead of the viewer's perspective.

It has a more sedate pace. You can change the speed variable if you want Scotty to give you warp 8. BTW, he hates doing that... ;)

Code: QB64: [Select]
  1. a& = _NEWIMAGE(600, 600, 32)
  2. TYPE star '                                                     define the star data type
  3.     x AS INTEGER
  4.     y AS INTEGER
  5.     z AS INTEGER
  6.     xa AS INTEGER
  7.     ya AS INTEGER
  8.  
  9. DIM SHARED max AS INTEGER: max = 500
  10. DIM SHARED vprt AS INTEGER: vprt = 600 '                        set the viewport setback from viewer's eye
  11. DIM SHARED p(max) AS star '                                     dimension the star data array
  12. DIM SHARED speed AS INTEGER: speed = 1 '                        warp factor
  13.  
  14. PopVoid '                                                       OldMoses said "Let there be light" and the universe was, is and ever shall be
  15. WINDOW (-300, 300)-(300, -300) '                                create viewport window, Cap'n Kirk spends his days staring at this
  16.  
  17. DO '                                                            draw the stars
  18.     CLS
  19.     FOR x = 1 TO max '                                          iterate through all stars
  20.         p(x).xa = p(x).x / Pythagorus(p(x)) * vprt '            get relative screen position from absolute position for x & y
  21.         p(x).ya = p(x).y / Pythagorus(p(x)) * vprt
  22.         IF ABS(p(x).xa) < 301 AND ABS(p(x).ya) < 301 THEN '     place the star if within the viewport
  23.             PSET (p(x).xa, p(x).ya)
  24.         END IF
  25.         p(x).z = p(x).z - speed '                               move the star closer to the viewer
  26.         IF p(x).z < 0 THEN ReplaceStar x '                      add new stars as existing ones go behind the viewer
  27.     NEXT x
  28.     _DISPLAY '                                                  eliminate screen flicker
  29.     _LIMIT 500 '                                                smooth out the action
  30.  
  31.  
  32. SUB PopVoid '                                                   Do an initial population of stars
  33.  
  34.     FOR x = 1 TO max '                                          place a 'max' # of stars randomly in a 3D space
  35.         RANDOMIZE TIMER
  36.         p(x).x = INT(RND * 5000) - 2500
  37.         p(x).y = INT(RND * 5000) - 2500
  38.         p(x).z = INT(RND * 5000) + 1
  39.     NEXT x
  40.  
  41. END SUB 'PopVoid
  42.  
  43.  
  44. FUNCTION Pythagorus (var1 AS star)
  45.  
  46.     'Use to find distance between two 3D points
  47.     'Also calculate speed of updated vectors
  48.  
  49.     DIM diff AS star
  50.     diff.x = ABS(var1.x)
  51.     diff.y = ABS(var1.y)
  52.     diff.z = ABS(var1.z)
  53.     horizontal = _HYPOT(diff.x, diff.y)
  54.     Pythagorus = _HYPOT(horizontal, diff.z)
  55.  
  56. END FUNCTION 'Pythagorus
  57.  
  58.  
  59. SUB ReplaceStar (var AS INTEGER) '                              This replaces any star that goes behind the viewer
  60.  
  61.     p(var).x = INT(RND * 5000) - 2500
  62.     p(var).y = INT(RND * 5000) - 2500
  63.     p(var).z = 5000
  64.  
  65. END SUB 'ReplaceStar
  66.  

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Help with Starfield
« Reply #13 on: August 10, 2019, 10:27:20 am »
Choice bite the bullet and learn some trig = how to use SIN and COS functions or go on being ignorant of some extremely useful tools for graphing.

If I want Ken to bite the bullet and learn SIN and COS use, I offer a quick tutorial on SIN and COS and apply it to Star Field creation and animation:

Here is my tutorial on SIN and COS use and applied to Star Field app.
Quote
about SIN and COS.txt 2019-08-10 B+

The first thing to know about SIN and COS functions used in BASIC is that they take Radian angles as arguments.

What is a Radian angle?
It is another unit of measure for angles expressed in terms of Pi. A circle is 2 * Pi radians, remember this one fact!
The more common unit of measure for angles is Degrees a circle is 360 Degrees.

Let us compare Degree angle measures with Radian measures:
A half circle is 360 Degrees / 2 = 180 Degrees,    a half circle in Radians is 2 * Pi / 2 = Pi
A forth circle is 360 Degrees / 4 = 90 Degrees,    a forth circle in Radians is 2 * Pi / 4 = Pi / 2 or 1/2 * Pi
A third circle is 360 Degrees / 3 = 120 Degrees,   a third circle in Radians is 2 * Pi / 3 = 2/3 * Pi
An nth of a circle is 360 / n Degrees,             an nth of a circle in Radians is 2 * Pi / n.

QB64 has a function _D2R(degreeAngle) that converts an angle measure from Degrees to Radians.
QB64 has a function that reverses that conversion _R2D that converts Radian angles to Degree angles.
QB64 also has a function for multiples of Pi = _PI(multiple), you can just use _PI if the multiple is 1.

In BASIC graphics:
0 Degrees or Radians are due East of the point in question often the center of the screen.
South is 90 Degrees or Pi / 2 Radians.
West is 180 Degrees or Pi Radians.
North is 270 Degrees or 3 / 2 * Pi.

Notice as Degrees or Radians increase you go Clockwise around a central point.



So what does SIN and COS have to do with programming, specially graphics?

Given some point (x, y) say the middle of the screen (_WIDTH / 2, _HEIGHT / 2),
say you want to know where a point(x, y) is that is 45 degrees SE of it and 100 pixels away.

These formula's will get you that point:
Lets call the coordinates for the center of the screen (xCenter, yCenter) often denoted (xc, yc) for short.
45 Degrees is 1/8 of circle or 2 * Pi / 8 ( a circle 2 * Pi divided 8 times)

x = xCenter + 100 * COS(2 * Pi / 8) 'plug in Radian values directly
y = yCenter + 100 * SIN(2 * Pi / 8)
or
x = xc + 100 * COS(_D2R(45)) ' let QB64 function do the conversion of 45 degrees to Radians
y = yc + 100 * SIN(_D2R(45))




Suppose we want to draw a Equilateral triangle about the center of the screen:
If you imagine 3 spokes coming out from center of screen to meet the 3 points of the triangle,
you can see that the points divide the circle evenly to 3 parts, angles are 2 * Pi / 3 in Radians.

The 3 points are 0, 1, and 2 multiples of the angle 2 * Pi / 3 = 0, 2/3 * Pi, 4/3 * Pi
(This is for an Equilateral Triangle that points dues East because the first point is at 0 Degrees = 0 Radians).
So the 6 calculations for the 3 points are (for Radius = R from center to Triangle point):
FOR i = 0 to 2
   x = xc + R * COS(i * _PI(2 / 3))
   y = yc + R * SIN(i * _PI(2 / 3))   
NEXT

Here is a quick little program to draw a triangle about the center of a screen:

Code: QB64: [Select]
  1.         SCREEN _NEWIMAGE(500, 500, 32)
  2.         DIM SHARED xc, yc    
  3.         xc = _WIDTH / 2 'middle of screen
  4.         yc = _HEIGHT / 2 ' middle of screen
  5.         R = 100
  6.         radianEquilateralAngle = _PI(2 / 3)
  7.         FOR i = 0 TO 3 ' we have to visit 4 points to return to place of start
  8.                 x = xc + R * COS(i * radianEquilateralAngle)
  9.                 y = yc + R * SIN(i * radianEquilateralAngle)
  10.                 IF i = 0 THEN PSET (x, y) ELSE LINE -(x, y)
  11.         NEXT
  12.         INPUT " Press enter to turn this triangle up! "; w$
  13.  
  14.         CLS
  15.         ' We can turn this triangle so that it points up
  16.         ' by adding 30 degrees = 2 * Pi / 12 Radians to the Angles in the SIN, COS functions.
  17.         FOR[co i = 0 TO 3 ' we have to visit 4 points to return to place of start
  18.                 'x = xc + R * COS(i * radianEquilateralAngle + _D2R(30))
  19.                 'y = yc + R * SIN(i * radianEquilateralAngle + _D2R(30))
  20.                 x = xc + R * COS(i * radianEquilateralAngle + _PI(2 / 12))
  21.                 y = yc + R * SIN(i * radianEquilateralAngle + _PI(2 / 12))
  22.                 IF i = 0 THEN PSET (x, y) ELSE LINE -(x, y)
  23.         NEXT

   
Now suppose we wish to create a Star Field about the center of the screen.
The center of the screen is important to build the stars around because to create the effect
of moving through the field we have to show the stars moving away from the center of the screen.

So we keep our xc, yc variables for the screen center and pick random angles and random distances to draw the stars.

   
'addition code added on for Star Field setup demo:
Code: QB64: [Select]
  1.         INPUT " Press enter to see demo of moving through Star Field "; w$
  2.         'Let the number of stars be:
  3.         nStars = 200
  4.  
  5.         ' Setup containers to save star data in, SHARE these containers for SUB access to them:
  6.         DIM SHARED starX(nStars), starY(nStars), starDX(nStars), starDY(nStars)
  7.  
  8.         'initialize the Stars with locations (x, y)
  9.         'and vectors dx, dy to represent the horizontal and vertical changes of the x and y axis
  10.         'they will be moving.
  11.  
  12.         ' Do this by writing a sub to do one star by it's index in the 4 star arrays.
  13.         ' See SUB newStar
  14.  
  15.         ' and then run newStars through a loop loading the star data containers with star info.
  16.         FOR i = 0 TO nStars
  17.                 newStar i
  18.         NEXT
  19.  
  20.         'setup main animation loop
  21.         DO
  22.                 CLS 'erase everything!
  23.                 'draw stars and update their location for next loop around unless they have moved beyond the screen
  24.                 FOR i = 0 TO nStars
  25.                         circleFill starX(i), starY(i), 1, _RGB32(255, 255, 255) 'draw it
  26.  
  27.                         'calc next frame loaction
  28.                         starX(i) = starX(i) + starDX(i)
  29.                         starY(i) = starY(i) + starDY(i)
  30.  
  31.                         ' are we still inside the screen? if not the make a new Star for the index i
  32.                         IF starX(i) < -2 OR starX(i) > _WIDTH + 2 THEN newStar i
  33.                         IF starY(i) < -2 OR starY(i) > _HEIGHT + 2 THEN newStar i
  34.                 NEXT
  35.                 _DISPLAY 'stop flicker from using CLS
  36.                 _LIMIT 100 ' nice even flow of frames and saves fan
  37.         LOOP UNTIL _KEYHIT = 27 'exit loop at esacoe key press
  38.  
  39.         SUB newStar (index)
  40.                 DIM rDegree, rDistance
  41.                 'setup stars by picking a random direction from the center of the screen and at a random distance
  42.                 'random direction = d in Degrees
  43.                 rDegree = RND * 360
  44.                 rDistance = RND * _WIDTH / 2 * SQR(2)
  45.  
  46.                 'using SIN and COS formulas for (x, y) about a center point
  47.                 'xc and yc are SHARED with main code
  48.                 starX(index) = xc + rDistance * COS(_D2R(rDegree))
  49.                 starY(index) = yc + rDistance * SIN(_D2R(rDegree))
  50.  
  51.                 'and the changes on x, y axis as stars move each  frame is
  52.                 starDX(index) = COS(_D2R(rDegree)) ' the change to the X coordinate
  53.                 starDY(index) = SIN(_D2R(rDegree)) ' the change to the Y coordinate
  54.         END SUB
  55.  
  56.         ' this is very handy if circles don't overlap
  57.         SUB circleFill (x, y, r, colr AS _UNSIGNED LONG)
  58.                 CIRCLE (x, y), r, colr
  59.                 IF r >= 1 THEN PAINT (x, y), colr, colr
  60.         END SUB
  61.  
  62.  
« Last Edit: August 10, 2019, 11:02:40 am by bplus »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Help with Starfield
« Reply #14 on: August 10, 2019, 10:36:09 am »
Here's my go at moving through a starfield; ala StarTrek warp drive:

Code: QB64: [Select]
  1. TYPE Dot_type
  2.     x AS _FLOAT
  3.     y AS _FLOAT
  4.     movex AS _FLOAT
  5.     movey AS _FLOAT
  6.     size AS _FLOAT
  7. DIM dots(10000) AS Dot_type
  8.  
  9.  
  10. SCREEN _NEWIMAGE(1024, 720, 32)
  11. WINDOW (-1000, -1000)-(1000, 1000)
  12.  
  13.  
  14. FOR x = -10 TO 10 'initialize dots
  15.     FOR y = -10 TO 10
  16.         dotsinplay = dotsinplay + 1
  17.         dots(dotsinplay).x = RND * 100 - 50
  18.         dots(dotsinplay).y = RND * 100 - 50
  19.         dots(dotsinplay).movex = RND * 10 - 5
  20.         dots(dotsinplay).movey = RND * 10 - 5
  21.         dots(dotsinplay).color = &HFF000000 + INT(RND * &HFFFFFF) + 1
  22.         dots(dotsinplay).size = RND * 5
  23.     NEXT
  24.  
  25.  
  26.  
  27.  
  28.     i = 1
  29.     DO 'move and replace dots which would go off screen
  30.         dots(i).x = dots(i).x + dots(i).movex
  31.         dots(i).y = dots(i).y + dots(i).movey
  32.         IF dots(i).x < -1000 OR dots(i).x > 1000 or _
  33.            dots(i).y < -1000 OR dots(i).y > 1000 THEN
  34.             dots(i).x = RND * 100 - 50
  35.             dots(i).y = RND * 100 - 50
  36.             dots(i).movex = RND * 10 - 5
  37.             dots(i).movey = RND * 10 - 5
  38.             dots(i).color = &HFF000000 + INT(RND * &HFFFFFF) + 1
  39.             dots(i).size = RND * 5
  40.         END IF
  41.         i = i + 1
  42.     LOOP UNTIL i >= dotsinplay
  43.     CLS
  44.     i = 1
  45.     DO 'display dots
  46.         CircleFill dots(i).x, dots(i).y, dots(i).size, dots(i).color
  47.         i = i + 1
  48.     LOOP UNTIL i >= dotsinplay
  49.     _DISPLAY
  50.  
  51. SUB CircleFill (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  52.     ' CX = center x coordinate
  53.     ' CY = center y coordinate
  54.     '  R = radius
  55.     '  C = fill color
  56.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  57.     DIM X AS INTEGER, Y AS INTEGER
  58.     Radius = ABS(R)
  59.     RadiusError = -Radius
  60.     X = Radius
  61.     Y = 0
  62.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  63.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  64.     WHILE X > Y
  65.         RadiusError = RadiusError + Y * 2 + 1
  66.         IF RadiusError >= 0 THEN
  67.             IF X <> Y + 1 THEN
  68.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  69.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  70.             END IF
  71.             X = X - 1
  72.             RadiusError = RadiusError - X * 2
  73.         END IF
  74.         Y = Y + 1
  75.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  76.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  77.     WEND
  78.  
  79.  

No trig involved at all.  (Unless you count the CircleFill routine, and it can be replaced with a PSET easily enough, which is what I used originally, and why our variable name is "dots".)

Concept is simple:  Choose a point on the screen.  Choose it a direction to move in.  Simply move it, and draw it, until it moves off screen, then repeat the process.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!