Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: QB: 3D-Starfield

Sivun loppuun

thefox [11.11.2002 12:53:25]

#

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 SUB

KimmoKM [12.11.2002 18:43:24]

#

Liian hidas.

Antti Laaksonen [12.11.2002 18:44:06]

#

Hienompaa avaruuslentoa on varmaan vaikea tehdä QBasicilla, etenkin kun laittaa tähtien määräksi vähän enemmän. Hyvä koodi :)

thefox [12.11.2002 18:47:58]

#

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.

KimmoKM [12.11.2002 18:55:33]

#

PS Kyllähän se upea on.

snakari [12.11.2002 20:22:17]

#

aika helvetin hieno kyllä on

HtH [12.11.2002 21:04:30]

#

sinien ja cosinien taulukointia ei kannata pentium koneille enää tehdä, suoritin osaa tehdä sen sen verran nopeasti, ettei muistia moiseen kannata tuhlata.

thefox [12.11.2002 23:11:40]

#

Joku on lukenut 3DICAnsa :) Minun kokemuksieni mukaan varsinkin noilla hitaimmilla Penttijumeilla nopeusero saattaa olla jopa ihan huomattava.. että näin :)

trinit [13.11.2002 12:41:37]

#

fawkz sai sitten kunnian olla 365. koodivinkin kirjoittaja :)

Pekkuli [13.11.2002 14:53:57]

#

Ei välttämättä kannatan sinien ja cosinien taulukointia tehdä, muttä mielestäni kannattaa aina ajatella hitaampien koneiden omistajia.

KimmoKM [13.11.2002 18:30:08]

#

Niin fawkz, oletkin kolmannensadannenkuudennenkymmenennenviidennen koodivinkin kirjoittaja.

Vilikki [13.11.2002 20:52:08]

#

Todella hieno koodi (hyvähän se on, että 365. koodia juhlistetaan vähän hienommalla koodilla... ;-) ). Vauhtikin oli juuri sopiva...

Gwaur [15.11.2002 23:24:42]

#

Super hieno, sitten vaan yritä tehdä tosta sellanen että kameraa voi manuaalisesti ohjata.

thefox [18.11.2002 11:00:56]

#

Helpostihan sellasen manuaalisen ohjauksen tuohon virittelee.. :)

Gwaur [21.11.2002 16:23:39]

#

no, teepä seuraavaan versioon sellanen sitten vai etkö tee?

thefox [21.11.2002 17:34:36]

#

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ää ;)

Gwaur [08.07.2003 18:49:22]

#

no ei missään nimesssä selviä mun tapauksessa :P

thefox [04.10.2003 15:35:20]

#

Noh, manuaalinen ohjaus onnistuu ihan vain pistämällä kiihtyvyydet (cam.xac, cam.yac, cam.zac) näppisohjattaviksi, ja ottamalla nuo satunnaissysteemit pois.

Meitsi [21.10.2004 01:35:25]

#

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.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta