Nothing earth shattering here, but just a little side project I have started working on, and this code might be useful to someone ..... feel free to use and abuse :)
SETSCREEN 640,480,1
LIMITFPS 60
TYPE star
x
y
z
ENDTYPE
GLOBAL stars[] AS star
SetupStars()
WHILE TRUE
UpdateStars()
DrawStars()
WEND
END
FUNCTION SetupStars:
LOCAL loop,loop2,num
FOR loop=1 TO 4
IF loop=1 THEN num=6
IF loop=2 THEN num=15
IF loop=3 THEN num=40
IF loop=4 THEN num=100
FOR loop2=1 TO num
LOCAL st AS star
st.x=RND(640)
st.y=RND(480)
st.z=loop
DIMPUSH stars[],st
NEXT
NEXT
ENDFUNCTION
FUNCTION UpdateStars:
FOREACH st IN stars[]
st.y=st.y+(1/st.z)
IF st.y>480
st.x=RND(640)
st.y=st.y-481
ENDIF
NEXT
ENDFUNCTION
FUNCTION DrawStars:
BLACKSCREEN
FOREACH st IN stars[]
LOCAL col=255-(st.z*50)
SETPIXEL st.x,st.y,RGB(col,col,col)
NEXT
SHOWSCREEN
ENDFUNCTION
Excellent stuff.
Here's a fake 3D starfield using the distance from the origin (centre of screen) to work out the speed of each star at any given point and a cheap parallax effect using a division modifier. I used to use this method in old 68000 days on the ST/Amiga using bitwise rotates as they were cheap and no need for SIN/COS tables. In GLB I've used multiply and divisions as speed is not the problem anymore :)
// --------------------------------- //
// Project: StarField
// Start: Sunday, January 13, 2008
// IDE Version: 5.129
SETSCREEN 640,480,1
LIMITFPS 60
TYPE star
x
y
ENDTYPE
GLOBAL stars[] AS star
GLOBAL xorigin = 320
GLOBAL yorigin = 240
SetupStars()
BLACKSCREEN
WHILE TRUE
UpdateStars()
DrawStars()
SHOWSCREEN
WEND
END
FUNCTION SetupStars:
LOCAL loop
FOR loop=1 TO 200
LOCAL st AS star
st.x=RND(32000) +50
IF (RND(1)) THEN st.x = -st.x
st.y=RND(24000) + 50
IF (RND(1)) THEN st.y = -st.y
DIMPUSH stars[],st
NEXT
ENDFUNCTION
FUNCTION UpdateStars:
LOCAL speed = 150, t = 0
FOREACH st IN stars[]
st.x = st.x + (st.x / speed)
st.y = st.y + (st.y / speed)
IF MOD ( t, BOUNDS( stars[], 0 )/10 )=0 THEN DEC speed, 10
INC t,1
IF st.y>22000 OR st.y < -22000 OR st.x>30000 OR st.x < -30000
st.y=RND(2000)+100
IF (RND(1)) THEN st.y = -st.y
st.x=RND(2000) +100
IF (RND(1)) THEN st.x = -st.x
ENDIF
NEXT
ENDFUNCTION
FUNCTION DrawStars:
FOREACH st IN stars[]
LOCAL col = ( ( ABS( st.x ) + ABS( st.y ) ) / 56000 ) * 255
SETPIXEL xorigin+ st.x / 100, yorigin+ st.y / 100 ,RGB(col,col,col)
NEXT
ENDFUNCTION
There's other ways to do this with calculation of the Z-axis, but I've always like this method for a quick and easy starfield/
Or how about a rotating / moving starfield ( yea uses sin/cos but this day and age shouldnt be a problem)
Use cursor keys left right to rotate
up down to speed up slow down
SETSCREEN 640,480,0
GLOBAL NumOfStars = 300 // how many stars on screen
TYPE star
x
y
ang
rad
speed
ENDTYPE
GLOBAL stars[] AS star
GLOBAL xorigin = 320
GLOBAL yorigin = 240
GLOBAL rotationspeed = 1
GLOBAL MAXSpeed = 0
SetupStars()
BLACKSCREEN
WHILE TRUE
IF KEY(203)
rotationspeed=rotationspeed-0.1
ENDIF
IF KEY(205)
rotationspeed=rotationspeed+0.1
ENDIF
IF KEY(208)
MAXSpeed = MAXSpeed - 0.01
IF MAXSpeed <= 0 // limit so the stars dont invert
MAXSpeed = 0
ENDIF
ENDIF
IF KEY(200)
MAXSpeed = MAXSpeed + 0.001
ENDIF
UpdateStars()
SHOWSCREEN
WEND
END
FUNCTION SetupStars:
LOCAL loop
FOR loop=1 TO NumOfStars
LOCAL st AS star
st.ang = RND(360) + 1
st.rad = RND(300) + 1
st.speed = (RND(10) + 5)/10
DIMPUSH stars[],st
NEXT
ENDFUNCTION
FUNCTION UpdateStars:
LOCAL col
FOREACH st IN stars[]
st.ang = st.ang - rotationspeed // turn the angle
st.rad = st.rad + st.speed // update distance
st.speed = st.speed + MAXSpeed // update speed
st.x = xorigin +(SIN(st.ang) * st.rad)
st.y = yorigin + (COS(st.ang) * st.rad)
IF st.rad > 400 // offscreen ? - reset star
st.ang = RND(360) + 1
st.rad = RND(50)
st.speed = (RND(10) + 5)/10
ENDIF
col = MOD( (st.rad / 350) * 255, 255) // make colour brighter
SETPIXEL st.x , st.y ,RGB(col,col,col)
NEXT
ENDFUNCTION
Wow! nice one ;)
Nice.
For PocketPC/GP2X there's a qmath.gbas in the Samples/Common folder. It defines QSIN and QSQR and stuff, which are much faster.
Okay, as the starfield coding seems to have been evolving :) (and because I fancied porting some Blitz code over), I've done a 3D starfield myself. Movement is currently randomized, but it will move in the x and y planes, and will rotate on the z axis, plus there is motion blur on the stars and variable brightness depending on their distance.
I wonder what the next offering will bring? :D
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// //
// Project: GLStarfield //
// //
// (C)opyright PeeJay 2008 www.peejays-remakes.co.uk //
// //
// A 3D Starfield with movement and motion blur - the full monty! :o) //
// //
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
SETSCREEN 640,480,0
LIMITFPS 60
GLOBAL ax,ay,az,axvel,ayvel,azvel,axacc,ayacc,azacc,cx,sx,cy,sy,cz,sz
TYPE star
x
y
z
zvel
prevx
prevy
ENDTYPE
GLOBAL stars[] AS star
SetupStars()
WHILE TRUE
axacc=axacc+((RND(12)-6)/10000)
ayacc=ayacc+((RND(12)-6)/10000)
azacc=azacc+((RND(12)-6)/10000)
axvel=axvel+axacc ; ayvel=ayvel+ayacc ; azvel=azvel+azacc
axacc=axacc*0.99 ; ayacc=ayacc*0.99 ; azacc=azacc*0.99
axvel=axvel*0.99 ; ayvel=ayvel*0.99 ; azvel=azvel*0.99
ax=(ax+axvel)*0.99 ; ay=(ay+ayvel)*0.99 ; az=(az+azvel)*0.99
cx=COS(ax) ; sx=SIN(ax) ; cy=COS(ay) ; sy=SIN(ay) ; cz=COS(az) ; sz=SIN(az)
DoStars()
WEND
END
FUNCTION SetupStars:
LOCAL loop
FOR loop=1 TO 300
LOCAL st AS star
st.x=RND(800)-400
st.y=RND(800)-400
st.z=100+RND(900)
st.zvel=RND(5)+0.5
st.prevx=-1000
st.prevy=0
DIMPUSH stars[],st
NEXT
ENDFUNCTION
FUNCTION DoStars:
LOCAL tx,tz,ty,tx2,x,y,xd,yd,bl,br
BLACKSCREEN
FOREACH st IN stars[]
IF st.prevx<0 OR st.prevx>640 OR st.prevy<0 OR st.prevy>480 OR st.z<1
st.x=RND(800)-400
st.y=RND(800)-400
st.z=100+RND(900)
st.zvel=RND(5)+0.5
st.prevx=-1000
st.prevy=0
ENDIF
st.z=st.z-st.zvel
tx=(st.x*cy)+(st.z*sy) ; tz=(st.z*cy)-(st.x*sy) ; ty=(st.y*cx)+(tz*sx)
tz=(tz*cx)-(st.y*sx) ; tx2=(tx*cz)+(ty*sz) ; ty=(ty*cz)-(tx*sz) ; tx=tx2
x=((tx/tz)*100)*3+320 ; y=((ty/tz)*100)*3+240
IF st.prevx=-1000
xd=0 ; yd=0 ; bl=1
ELSE
xd=x-st.prevx ; yd=y-st.prevy ; bl=SQR((xd*xd)+(yd*yd))
ENDIF
br=255-((st.z*255)/1000) ; br=(br*st.zvel)/6
IF bl>1 AND bl<50
DRAWLINE x,y,st.prevx,st.prevy,RGB(br,br,br)
ELSE
SETPIXEL x,y,RGB(br,br,br)
ENDIF
st.prevx=x ; st.prevy=y
NEXT
SHOWSCREEN
ENDFUNCTION
o.O Fat!
awesome!
OK, not looked at the others, but as this is a star field thread, thought I`d post mine too ...
// --------------------------------- //
// Project: Starfield
// Start: Thursday, January 24, 2008
// IDE Version: 5.146
TYPE star
ang
pos
ENDTYPE
GLOBAL str AS star
LOCAL strz[] AS star
FOR m=1 TO 100
str.ang=RND(360)
str.pos=RND(200)
DIMPUSH strz[],str
NEXT
SETSCREEN 640,480,1
WHILE(0=0)
ALPHAMODE 1
show_stars(strz[],0.25,-0.1)
ALPHAMODE -0.255
DRAWRECT 0,0,1280,1024,RGB(32,32,32)
USEASBMP
SHOWSCREEN
WEND
// ------------------------------------------------------------- //
// --- SHOW_STARS ---
// ------------------------------------------------------------- //
FUNCTION show_stars: stz[] AS star,spd,rot
// These values are defined LOCAL:
//
LOCAL spd
LOCAL rot
flag=0
scx=320
scy=240
FOREACH str IN stz[]
a=str.ang
p=str.pos
FOR q=1 TO 4 STEP 1
qq=q*vv
i=((100.0)/p)*100
xx=(SIN(a)*i)*q
yy=(COS(a)*i)*q
ik=i/2
IF ik>255 THEN ik=255
SETPIXEL scx+xx+1,scy+yy,RGB(ik,ik,ik)
SETPIXEL scx+xx-1,scy+yy,RGB(ik,ik,ik)
SETPIXEL scx+xx,scy+yy-1,RGB(ik,ik,ik)
SETPIXEL scx+xx,scy+yy+1,RGB(ik,ik,ik)
ik=ik*2
IF ik>255 THEN ik=255
SETPIXEL scx+xx,scy+yy,RGB(0,ik,ik)
a=a+90
IF a>360 THEN a=a-360
NEXT
p=p-spd
a=a-rot
IF a>360 THEN a=a-360
IF p>200 THEN p=1
IF p<1 THEN p=200
str.pos=p
str.ang=a
NEXT
ENDFUNCTION // SHOW_STARS
Hi i needed help to understand how to store data in Arrays, I didnt understand the examples above fully so i set about writing my own parallax star field... It has really helped me understand and is written out very simply, uses 2 arrays, no types and could be reproduced even shorter but of course that would make it more complicated for a noob... like me. It looks great and is just 23 lines of code =D
//Simple 3 layer Parallax stars by Phil Lewis-- (fully comented-->)
SETSCREEN 640, 480, 1
//--(Setup DIM storage & Random x y coordinate generator)--
DIM x[1000] // I want to store 1000 x coordinates (0-999)
DIM y[1000] // I want to store 1000 y coordinates (0-999)
FOR loop=0 TO 1000 -1 // loop the commands 999 times in between FOR and NEXT
x[loop]=RND(640) // adding random values to y (using loop above)
y[loop]=RND(480) // adding random values to y (using loop above)
NEXT // go back to FOR (until loop is exhausted)
//--(Draw (Back) pixels at the x and y coordinates)--
WHILE TRUE // Repeat the commands between WHILE and WEND
FOR loop2 = 0 TO 100 - 1 // loop the commands 99 times in between FOR and NEXT
y[loop2]= y[loop2] + 0.3 // 0.3 pixel per frame is added to each y coordinate
SETPIXEL x[loop2], y[loop2], RGB(100,100,100) // draw pixels @ x & y coordinates
IF y[loop2] > 480 THEN y[loop2] =y[loop2] - 480 // y is set to top of screen when it reaches the bottom
NEXT // Go back to FOR
//------------------(middle)-------------------------
FOR loop3 = 200 TO 270 - 1 // loop the commands 99 times in between FOR and NEXT
y[loop3]= y[loop3] + 0.5 // 0.3 pixel per frame is added to each y coordinate
SETPIXEL x[loop3], y[loop3], RGB(150,150,150) // draw pixels @ x & y coordinates
IF y[loop3] > 480 THEN y[loop3] =y[loop3] - 480 // y is set to top of screen when it reaches the bottom
NEXT // Go back to FOR
//------------------(Front)--------------------------
FOR loop4 = 300 TO 330 - 1 // loop the commands 99 times in between FOR and NEXT
y[loop4]= y[loop4] + 1 // 0.3 pixel per frame is added to each y coordinate
SETPIXEL x[loop4], y[loop4], RGB(255,255,255) // draw pixels @ x & y coordinates
IF y[loop4] > 480 THEN y[loop4] =y[loop4] - 480 // y is set to top of screen when it reaches the bottom
NEXT // Go back to FOR
SHOWSCREEN // Print everything so far to the screen
WEND // Go back to WHILE
That would be easier if you used TYPE's to record the colour and position - that way, you could (theoretically) have up to 255 layers.