Eli tuossa olis tuollanen 3D-starfield. Antialiasoidut pikselit ja jonkinlainen kamerarotaatio.. ihan hienolta näyttää omasta mielestäni :)
Tohon voi jotain delayta viritellä jos tuntuu että pyörii liian nopsaan.. tai sitten lisää tähtien määrää.
' 3D-starfield with antialiased pixels and camera
' Author: fawkz <_____@luukku.com>
' You can put up somekind of delay if it runs too fast for you...
' ..or increase the amount of stars.
' For my 150MHz Pentium 200 stars seems to be a quite good value..
' Not too fast, but not too slow neither.
' On a GHz-puter you might want maybe about 1000-2000 stars :)
DEFINT A-Z
DECLARE SUB APIXEL (wx AS DOUBLE, wy AS DOUBLE, c AS DOUBLE)
' 320x200 w/ 256 colors.. good ol' mode13h
SCREEN 13
' set grayscale-palette
OUT &H3C8, 0
FOR c = 0 TO 255
  OUT &H3C9, INT(c / 4)
  OUT &H3C9, INT(c / 4)
  OUT &H3C9, INT(c / 4)
NEXT
' type for 3d-star
TYPE star3
  x AS DOUBLE
  y AS DOUBLE
  z AS DOUBLE
  v AS DOUBLE ' velocity
END TYPE
' this is type for star when it's projected to 2d-cordinates
TYPE star2
  x AS DOUBLE
  y AS DOUBLE
END TYPE
' camera -type, it doesn't have a position (because we don't need it :)
' just an angles.. and velocities for it's movement
TYPE camera
  xan AS DOUBLE ' angles for each x, y, and z
  yan AS DOUBLE
  zan AS DOUBLE
  xve AS DOUBLE ' velocities
  yve AS DOUBLE
  zve AS DOUBLE
  xac AS DOUBLE ' accelerations
  yac AS DOUBLE
  zac AS DOUBLE
END TYPE
CONST CENTERX = 160   ' screen horizontal center
CONST CENTERY = 100   ' and vertical..
CONST STARS = 200     ' amount of stars (will be 0-STARS so 200 means 201 stars)
CONST SCALE = 255     ' scale
CONST ACC = .00001    ' acceleration value
CONST DAMP = .99      ' damping value for smooth movement..
DIM s(STARS) AS star3   ' 3d-stars..
DIM ss(STARS) AS star2  ' ..projected to 2d-screen
DIM n AS star3          ' for 3d-rotation
DIM r AS star3          ' rotated position
DIM cam AS camera       ' make a camera :)
RANDOMIZE TIMER         ' initialize rng by timer
FOR i = 0 TO STARS      ' get random positions+velocities for stars
  s(i).x = (RND * 1000) - 500
  s(i).y = (RND * 1000) - 500
  s(i).z = (RND * 100) + 900
  s(i).v = (RND * 50) + 5
NEXT i
DO
  ' handle camera-rotations, increase accelerations
  cam.xac = (cam.xac + (RND * ACC * 2) - ACC)
  cam.yac = (cam.yac + (RND * ACC * 2) - ACC)
  cam.zac = (cam.zac + (RND * ACC * 2) - ACC)
  ' increase velocities (accelerate)
  cam.xve = cam.xve + cam.xac
  cam.yve = cam.yve + cam.yac
  cam.zve = cam.zve + cam.zac
  ' damp the motion (will go more and more towards zero)
  cam.xac = cam.xac * DAMP
  cam.yac = cam.yac * DAMP
  cam.zac = cam.zac * DAMP
  ' ..same here
  cam.xve = cam.xve * DAMP
  cam.yve = cam.yve * DAMP
  cam.zve = cam.zve * DAMP
  ' get new angles.. move the camera..
  cam.xan = (cam.xan + cam.xve) * DAMP
  cam.yan = (cam.yan + cam.yve) * DAMP
  cam.zan = (cam.zan + cam.zve) * DAMP
  FOR i = 0 TO STARS               ' loop for all stars..
    APIXEL ss(i).x, ss(i).y, 0       ' erase old star
    s(i).z = s(i).z - s(i).v         ' move star on z-axis
    ' rotate stars.. based on the camera-angle
    ' around the x-axis
    n.y = COS(cam.xan) * s(i).y - SIN(cam.xan) * s(i).z
    n.z = SIN(cam.xan) * s(i).y - COS(cam.xan) * s(i).z
    ' around the y-axis
    n.x = COS(cam.yan) * s(i).x + SIN(cam.yan) * n.z
    r.z = -SIN(cam.yan) * s(i).x + COS(cam.yan) * n.z
    ' and around the z-axis
    r.x = COS(cam.zan) * n.x - SIN(cam.zan) * n.y
    r.y = SIN(cam.zan) * n.x + COS(cam.zan) * n.y
    ' project the stars to screen 2d-coordinates
    ss(i).x = r.x / r.z * SCALE + CENTERX
    ss(i).y = r.y / r.z * SCALE + CENTERY
    IF ss(i).x < 0 OR ss(i).x > CENTERX * 2 OR ss(i).y < 0 OR ss(i).y > CENTERY * 2 OR s(i).z < 1 THEN
      ' if star out from screen or z below zero..
      ' get a new random position & velocity for star
      s(i).x = (RND * 1000) - 500
      s(i).y = (RND * 1000) - 500
      s(i).z = (RND * 100) + 900
      s(i).v = (RND * 50) + 5
    END IF
    ' plot antialiased pixel.. :)
    APIXEL ss(i).x, ss(i).y, 255 - (s(i).z * (255 / 1000))
  NEXT
LOOP UNTIL INKEY$ = CHR$(27) ' loop until ESC-pressed
DEFSNG A-Z
SUB APIXEL (wx AS DOUBLE, wy AS DOUBLE, c AS DOUBLE)
  ' antialiased-pixel routine.. basicly the "pixel"
  ' consists of 4 pixels, which colors are calculated
  ' based on the position (floating point) of them..
  ' wx & wy are coordinates, c is brightness
  DIM x AS LONG, y AS LONG
  DIM fx AS DOUBLE, fy AS DOUBLE
  DIM btl AS LONG, btr AS LONG, bbl AS LONG, bbr AS LONG
  x = INT(wx): y = INT(wy)                ' integer part
  fx = wx - x: fy = wy - y                ' fractional part
  ' calculate colors
  btl = (1 - fx) * (1 - fy) * c
  btr = (fx) * (1 - fy) * c
  bbl = (1 - fx) * (fy) * c
  bbr = (fx) * (fy) * c
  ' put pixels
  PSET (x, y), btl
  PSET (x + 1, y), btr
  PSET (x, y + 1), bbl
  PSET (x + 1, y + 1), bbr
END SUBLiian hidas.
Hienompaa avaruuslentoa on varmaan vaikea tehdä QBasicilla, etenkin kun laittaa tähtien määräksi vähän enemmän. Hyvä koodi :)
Juuh no kyllähän tuossa optimoimisen varaa olisi.. sinit ja kosinit voisi taulukoida jne. mutta koodivinkkien ollessa kyseessä näitä tuskin kannattaa lähteä turhan paljon viilailemaan.
PS Kyllähän se upea on.
aika helvetin hieno kyllä on
sinien ja cosinien taulukointia ei kannata pentium koneille enää tehdä, suoritin osaa tehdä sen sen verran nopeasti, ettei muistia moiseen kannata tuhlata.
Joku on lukenut 3DICAnsa :) Minun kokemuksieni mukaan varsinkin noilla hitaimmilla Penttijumeilla nopeusero saattaa olla jopa ihan huomattava.. että näin :)
fawkz sai sitten kunnian olla 365. koodivinkin kirjoittaja :)
Ei välttämättä kannatan sinien ja cosinien taulukointia tehdä, muttä mielestäni kannattaa aina ajatella hitaampien koneiden omistajia.
Niin fawkz, oletkin kolmannensadannenkuudennenkymmenennenviidennen koodivinkin kirjoittaja.
Todella hieno koodi (hyvähän se on, että 365. koodia juhlistetaan vähän hienommalla koodilla... ;-) ). Vauhtikin oli juuri sopiva...
Super hieno, sitten vaan yritä tehdä tosta sellanen että kameraa voi manuaalisesti ohjata.
Helpostihan sellasen manuaalisen ohjauksen tuohon virittelee.. :)
no, teepä seuraavaan versioon sellanen sitten vai etkö tee?
Enpä jaksa postailla niitä "3d-starfield *nyt toimii*" sun muita. Melko simppeliä koodia tuo IMO on että kyllä se pitäis selvitä jos mistään mitään tietää ;)
no ei missään nimesssä selviä mun tapauksessa :P
Noh, manuaalinen ohjaus onnistuu ihan vain pistämällä kiihtyvyydet (cam.xac, cam.yac, cam.zac) näppisohjattaviksi, ja ottamalla nuo satunnaissysteemit pois.
Toimii, mutta dosboksilla aivan tajuttoman hitaasti. Aluksi kokeilin että tähtiä olisi 1000 ---> tiltti. Kokeilin sitten 200 --> bugittaa. Lopuksi kokeilin 30 -> toimii mutta h-i-t-a-a-s-t-i. Ja silloinkin nopeus oli jotain tyyliin 6 fps.
Aihe on jo aika vanha, joten et voi enää vastata siihen.