0,]']±>Sï}WÿÍu§ðp8·d%qy)6o;]ÉA¦ösï÷ôôô”°ÂVl†3b and b or v) end local function dot(x,y,c) if x>=0 and x<240 and y>=0 and y<136 then pix(x,y,c) end end local SUN={2,3,4,12} local ICE={13,12,12} local LAND={7,6,5} local OCEAN={8,9,10} local CLOUD={14,13,12} local DARKM={1,1,2} local SPOT={1,2,3} local MR={14,13,12} local RC={14,14,13,4,12,4,13,4,13,13,14} local P={ {n="Mercury",r=24, R=2.0,yr=0.24,au="0.39 AU",per="88 days", tilt=0.0, sr=1.5,k=0,ramp={15,14,13}}, {n="Venus", r=34, R=3.2,yr=0.62,au="0.72 AU",per="225 days",tilt=0.05,sr=1, k=0,ramp={3,4,12}}, {n="Earth", r=46, R=3.4,yr=1.0, au="1.00 AU",per="365 days",tilt=0.41,sr=3, k=1,ramp={8,9,10}, mn={{7,2.5,1.0}}}, {n="Mars", r=58, R=2.4,yr=1.88,au="1.52 AU",per="687 days",tilt=0.44,sr=3, k=2,ramp={1,2,3}, mn={{4.5,5,0.5},{7,3,0.4}}}, {n="Jupiter",r=100,R=8.0,yr=11.9,au="5.20 AU",per="11.9 yrs",tilt=0.05,sr=6, k=3,bf=9,A={2,3,4},B={3,4,12},ramp={2,3,4},spot=true, mn={{13,4,1.1,{3,4,12}},{17,2.6,1.0,{13,12,12}},{22,1.6,1.6},{29,0.9,1.4,{14,13,4}}}}, {n="Saturn", r=128,R=7.0,yr=29.5,au="9.58 AU",per="29.5 yrs",tilt=0.47,sr=5, k=3,bf=5,A={3,4,12},B={2,3,4},ramp={3,4,12},ring=true, mn={{26,1,1.6,{2,3,4}},{32,0.6,0.9}}}, {n="Uranus", r=152,R=5.0,yr=84, au="19.2 AU",per="84 yrs", tilt=1.7, sr=3, k=0,ramp={7,11,12}, mn={{9,2,0.8}}}, {n="Neptune",r=172,R=5.0,yr=165, au="30.1 AU",per="165 yrs", tilt=0.5, sr=3, k=3,bf=3,A={8,9,10},B={9,10,11},ramp={8,9,10}, mn={{10,-1.5,1.0}}}, } for i,p in ipairs(P) do p.w=0.5*p.yr^-0.6 p.a0=i*0.8+0.3 if p.mn then for _,m in ipairs(p.mn) do m.pl={k=0,ramp=m[4] or MR} end end end local AST={} for i=1,260 do AST[i]={r=66+rnd()*14,a=rnd()*TAU,y=(rnd()-0.5)*3,w=0.2*(1+(rnd()-0.5)*0.2),c=({13,14,14,15})[rnd(4)]} end local ST={} for i=1,500 do local x,y,z=rnd()-0.5,rnd()-0.5,rnd()-0.5 local l=sqrt(x*x+y*y+z*z) if l<0.05 then l=1 end ST[i]={x/l,y/l,z/l,({15,14,14,13,12})[rnd(5)]} end local TG={ {n="SOLAR SYSTEM",info="Overview",R=0,dist=480}, {n="SUN",info="G-type star 5500 C surface",R=SR,dist=SR*6+12}, } for _,p in ipairs(P) do TG[#TG+1]={n=string.upper(p.n),info=p.au.." Year: "..p.per,R=p.R,dist=p.R*8+8,p=p} end local t=0 local yaw,pit=0.5,0.5 local cdist,tdist=480,480 local cx,cy,cz=0,0,0 local foc=1 local spds={0.3,1,3,10,0} local si=2 local lmx,lmy,lml=0,0,false local cyw,syw,cpt,spt=1,0,1,0 local UX,UY,UZ,AX,AY,AZ,BX,BY,BZ=0,1,0,1,0,0,0,0,1 local LX,LY,LZ,SPIN=0,0,-1,0 local function vrot(x,y,z) local x1=x*cyw-z*syw local z1=x*syw+z*cyw return x1,y*cpt+z1*spt,-y*spt+z1*cpt end local function view(x,y,z) return vrot(x-cx,y-cy,z-cz) end local function shade(i,px,py) local k=i*2.6+0.35+(((px+py)&1)-0.5)*0.8 local idx=floor(k) if idx<0 then idx=0 elseif idx>2 then idx=2 end return idx+1 end local function sphere(sx,sy,rad,pl) local x0,y0=floor(sx+0.5),floor(sy+0.5) local r2=rad*rad local kd,ramp=pl.k,pl.ramp local ya,yb=max(-rad,-y0),min(rad,135-y0) local xa,xb=max(-rad,-x0),min(rad,239-x0) for dy=ya,yb do for dx=xa,xb do local q=dx*dx+dy*dy if q<=r2 then local nx,ny=dx/rad,-dy/rad local nz=-sqrt(1-q/r2) local i=nx*LX+ny*LY+nz*LZ local rp=ramp if kd>0 then local lat=nx*UX+ny*UY+nz*UZ if kd==1 then local lon=atan(nx*AX+ny*AY+nz*AZ,nx*BX+ny*BY+nz*BZ)+SPIN local v=sin(lon*2+1)*cos(lat*2.5)+0.6*sin(lon*5+lat*3)+0.4*cos(lon*3-lat*6) if abs(lat)>0.88 then rp=ICE elseif v>0.55 then rp=LAND else rp=OCEAN end if abs(lat)<0.88 and sin(lon*3+lat*7)*sin(lon*5-lat*3+1.3)>0.6 then rp=CLOUD end elseif kd==2 then local lon=atan(nx*AX+ny*AY+nz*AZ,nx*BX+ny*BY+nz*BZ)+SPIN local v=sin(lon*3)*cos(lat*3)+0.5*sin(lon*7+lat*4) if abs(lat)>0.9 then rp=ICE elseif v>0.35 then rp=DARKM end else local bnd=floor((lat+1)*pl.bf)%2 rp=bnd==0 and pl.A or pl.B if pl.spot then local lon=(atan(nx*AX+ny*AY+nz*AZ,nx*BX+ny*BY+nz*BZ)+SPIN)%TAU if (lon-3.0)^2*5+(lat+0.35)^2*55<1 then rp=SPOT end end end end local px,py=x0+dx,y0+dy pix(px,py,rp[shade(i,px,py)]) end end end end local function drawSun(sx,sy,rad) local x0,y0=floor(sx+0.5),floor(sy+0.5) local r2=rad*rad local ya,yb=max(-rad,-y0),min(rad,135-y0) local xa,xb=max(-rad,-x0),min(rad,239-x0) for dy=ya,yb do for dx=xa,xb do local q=dx*dx+dy*dy if q<=r2 then local nx,ny=dx/rad,-dy/rad local nz=sqrt(1-q/r2) local v=nz*0.85+0.18*sin(nx*10+t*4)*cos(ny*9-t*3)+0.12*sin((nx+ny)*17-t*5) local px,py=x0+dx,y0+dy local k=v*3.6+(((px+py)&1)-0.5)*0.8 local idx=floor(k) if idx<0 then idx=0 elseif idx>3 then idx=3 end pix(px,py,SUN[idx+1]) end end end local rr0=max(rad,3) for i=1,70 do local a=rnd()*TAU local rr=rad+1+rnd()*rnd()*rr0*0.9 dot(x0+cos(a)*rr,y0+sin(a)*rr,rr1.72 and k<1.8) then local rr=p.R*k local c=RC[n] or 13 local steps=clamp(floor(TAU*rr*b.f*1.2),24,420) for j=0,steps do local th=j/steps*TAU local ct,st=cos(th),sin(th) local x,y,z=view(p.x+rr*ct*tc,p.y+rr*ct*ts,p.z+rr*st) local d=z+cdist if d>1 and ((z0 and g.R*3+6 or 40 tdist=clamp(tdist,lo,650) t=t+0.01*spds[si] cyw,syw=cos(yaw),sin(yaw) cpt,spt=cos(pit),sin(pit) for _,p in ipairs(P) do local a=p.a0+t*p.w p.x,p.y,p.z=cos(a)*p.r,0,sin(a)*p.r*0.96 p.b=nil end local tx,ty,tz=0,0,0 if g.p then tx,ty,tz=g.p.x,g.p.y,g.p.z end cx=cx+(tx-cx)*0.25 cy=cy+(ty-cy)*0.25 cz=cz+(tz-cz)*0.25 cdist=cdist+(tdist-cdist)*0.12 cls(0) for _,s in ipairs(ST) do local x,y,z=vrot(s[1],s[2],s[3]) if z>0.05 then dot(120+x/z*150,68-y/z*150,s[4]) end end if cdist>150 then for _,p in ipairs(P) do local c=(g.p==p) and 14 or 15 for j=0,119 do local a=j/120*TAU local x,y,z=view(cos(a)*p.r,0,sin(a)*p.r*0.96) local d=z+cdist if d>1 then local f=FOV/d dot(120+x*f,68-y*f,c) end end end end for _,a in ipairs(AST) do local ang=a.a+t*a.w local x,y,z=view(cos(ang)*a.r,a.y,sin(ang)*a.r*0.96) local d=z+cdist if d>1 then local f=FOV/d local rr=f*0.3 if rr>=1 then circ(floor(120+x*f),floor(68-y*f),floor(rr),a.c) else dot(120+x*f,68-y*f,a.c) end end end local B={} local x,y,z=view(0,0,0) local d=z+cdist if d>1 then local f=FOV/d B[#B+1]={k=0,z=z,sx=120+x*f,sy=68-y*f,f=f,rad=SR*f,wx=0,wy=0,wz=0} end for _,p in ipairs(P) do x,y,z=view(p.x,p.y,p.z) d=z+cdist if d>1 then local f=FOV/d local b={k=1,p=p,z=z,sx=120+x*f,sy=68-y*f,f=f,rad=p.R*f,wx=p.x,wy=p.y,wz=p.z} B[#B+1]=b p.b=b end if p.mn then for i,m in ipairs(p.mn) do local a=t*m[2]+i*1.7 local wx=p.x+cos(a)*m[1] local wy=p.y+sin(a)*m[1]*0.12 local wz=p.z+sin(a)*m[1] local mx2,my2,mz2=view(wx,wy,wz) local dd=mz2+cdist if dd>1 then local f=FOV/dd B[#B+1]={k=2,pl=m.pl,z=mz2,sx=120+mx2*f,sy=68-my2*f,f=f,rad=m[3]*f,wx=wx,wy=wy,wz=wz} end end end end table.sort(B,function(a,b) return a.z>b.z end) for _,b in ipairs(B) do local lx,ly,lz=vrot(-b.wx,-b.wy,-b.wz) local l=sqrt(b.wx*b.wx+b.wy*b.wy+b.wz*b.wz) if l<1 then l=1 end LX,LY,LZ=lx/l,ly/l,lz/l local rad=max(1,floor(b.rad+0.5)) if b.k==0 then drawSun(b.sx,b.sy,rad) elseif b.k==1 then local p=b.p local ts,tc=sin(p.tilt),cos(p.tilt) UX,UY,UZ=vrot(-ts,tc,0) AX,AY,AZ=vrot(tc,ts,0) BX,BY,BZ=vrot(0,0,1) SPIN=t*p.sr if p.ring then ring(b,false) end if rad<=1 then circ(floor(b.sx),floor(b.sy),1,p.ramp[2]) else sphere(b.sx,b.sy,rad,p) end if p.ring then ring(b,true) end else if rad<=1 then dot(b.sx,b.sy,b.pl.ramp[3]) else sphere(b.sx,b.sy,rad,b.pl) end end end if cdist>150 then for _,p in ipairs(P) do if p.b then local c=(g.p==p) and 12 or 13 print(p.n,floor(p.b.sx)+max(2,floor(p.b.rad))+3,floor(p.b.sy)-3,c,false,1,true) end end end rect(0,0,240,8,0) rect(0,128,240,8,0) local w=print(g.n,3,1,4,false,1,true) print(g.info,3+w+6,1,13,false,1,true) local sp=spds[si]==0 and "PAUSED" or "SPEED x"..spds[si] print(sp,240-print(sp,0,-10,0,false,1,true)-3,1,12,false,1,true) print("ARROWS:ROTATE Z/X:ZOOM A:NEXT S:SPEED M:MUSIC",3,130,14,false,1,true) end