我玩了几天"RollerCoaster Tycoon"(过山车大亨),它那精美的过山车造型真是令人着迷。想不想自己动手写一个过山车模拟器?下面就是我的尝试。 程序中输入一个设计好的轨道抽象数据,产生一条细致光滑的三维视角的轨道(段与段之间是互切的)。借助这个小程序,你可以尝试逐步的完成新的轨道设计。 过山车轨道的生成程序 RollerCoaster2.m function [d,s]=drawRollerCoaster(path,step) %-1 /2 \3 R4 L5 %path 中的1表示直道,2表示提升,3表示降低,4表示右转,5表示左转 %step 是每一步移动的距离 %d是详细的轨迹、s是各段的端点 error=0; way=zeros(1,length(path)+2); way(1)=1; way(2:length(path)+1)=path; way(length(path)+2)=1; slice=10; turn=[0 1; -1 0]; img=[ 1 0; 0 -1]; t=flat2up(step,slice); t2=[t(1:2,:); t(slice)-[t(3,slice-1:-1:1),0]]; v=turnright(step,slice); v2=[(v(1:2,:)'*img)';v(3,:)]; dir=0; h=zeros(3,1000);h(1,1)=0; h(2,1)=0; h(3,1)=0; ch=2; j=zeros(3,100); j(:,1)=h(1); cj=2; for i=2:length(way)-1 switch way(i) case 1, switch way(i-1) case {1,4,5} h(1,ch)=step*cos(dir*pi/2)+h(1,ch-1); h(2,ch)=step*sin(dir*pi/2)+h(2,ch-1); h(3,ch)=h(3,ch-1); ch=ch+1; j(:,cj)=h(:,ch-1); cj=cj+1; case 2, h(:,ch:ch+slice-1)=[(t2(1:2,:)'*(turn^dir))';t2(3,:)]+h(:,ch-1)*ones(1,slice); ch=ch+slice; j(:,cj)=h(:,ch-1); cj=cj+1; case 3, h(:,ch:ch+slice-1)=[(t2(1:2,:)'*(turn^dir))';-t2(3,:)]+h(:,ch-1)*ones(1,slice); ch=ch+slice; j(:,cj)=h(:,ch-1); cj=cj+1; end; case 2, switch way(i-1) case {1,4,5} h(:,ch:ch+slice-1)=[(t(1:2,:)'*(turn^dir))';t(3,:)]+h(:,ch-1)*ones(1,slice); ch=ch+slice; j(:,cj)=h(:,ch-1); cj=cj+1; case 2, h(1,ch)=step*cos(dir*pi/2)+h(1,ch-1); h(2,ch)=step*sin(dir*pi/2)+h(2,ch-1); h(3,ch)=step+h(3,ch-1); ch=ch+1; j(:,cj)=h(:,ch-1); cj=cj+1; otherwise, errin(i); error=1; end; case 3, switch way(i-1) case {1,4,5} h(:,ch:ch+slice-1)=[(t(1:2,:)'*(turn^dir))';-t(3,:)]+h(:,ch-1)*ones(1,slice); ch=ch+slice; j(:,cj)=h(:,ch-1); cj=cj+1; case 3, h(1,ch)=step*cos(dir*pi/2)+h(1,ch-1); h(2,ch)=step*sin(dir*pi/2)+h(2,ch-1); h(3,ch)=-step+h(3,ch-1); ch=ch+1; j(:,cj)=h(:,ch-1); cj=cj+1; otherwise, errin(i); error=1; end; case 4, switch way(i-1) case {1,4,5}, h(:,ch:ch+slice-1)=[(v(1:2,:)'*(turn^dir))';v(3,:)]+h(:,ch-1)*ones(1,slice); ch=ch+slice; dir=dir+1; j(:,cj)=h(:,ch-1); cj=cj+1; otherwise, errin(i); error=1; end; case 5, switch way(i-1) case {1,4,5}, h(:,ch:ch+slice-1)=[(v2(1:2,:)'*(turn^dir))';v2(3,:)]+h(:,ch-1)*ones(1,slice); ch=ch+slice; dir=dir-1; j(:,cj)=h(:,ch-1); cj=cj+1; otherwise, errin(i); error=1; end; end; end; d=h(:,1:ch-1); s=j(:,1:cj-1); function flatup=flat2up(step,slice) Radius=step/cos(pi/8)/2/sin(pi/8); flatup=zeros(3,slice); c=1; for alpha=0+pi/4/slice:pi/4/slice:pi/4 l=Radius*sin(alpha/2)*2; flatup(1,c)=l*cos(alpha/2); flatup(2,c)=0; flatup(3,c)=l*sin(alpha/2); c=c+1; end; function tr=turnright(step,slice) c=1; for alpha=-pi/2+pi/2/slice:pi/2/slice:0 tr(1,c)=step*cos(alpha); tr(2,c)=step*sin(alpha)+step; tr(3,c)=0; c=c+1; end; function errin(number) disp(['Error in sequence at ',int2str(number),'\n']) 主程序 w=[1,1,1,2,2,1,3,3,1,4,4,5,1,2,2,2,1,5,5,1,1,1,5,2,2,1,3,3,3,1,5,4,1,2,1,3,1,4,1,1,1,1,4,3,3,1,1]; [d,e]=RollerCoaster2(w,10); hold off; plot3(d(1,:),d(2,:),d(3,:)); hold on; plot3([e(1,:);e(1,:)],[e(2,:);e(2,:)],[e(3,:);zeros(1,size(e,2))],'r'); axis equal grid on xlabel('x'); ylabel('y'); zlabel('z'); p = plot3(0,0,0,'square', ... 'EraseMode','xor','MarkerSize',5,'MarkerFaceColor',[1,0.7,0.7]) for i=2:size(e,2) set(p,'XData',e(1,i),'YData',e(2,i),'ZData',e(3,i)) pause; drawnow end axis equal grid on xlabel('x'); ylabel('y'); zlabel('z'); hold off; 如图所示,蓝线表示轨道,红线表示支柱,一个小方块随着键盘的按键在轨道上移动。你可以任意改变视角来观察方块的运动。 很明显,这个程序还很粗糙,但很快你就可以在这里看到它的新版本了。可能增添的特性有:轨道由线升级到面,支柱变成圆柱,在线的修改轨道,自动闭合轨道。 (责任编辑:泉水) |