<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
使用鍵盤上方向鍵↑向前移動
使用鍵盤左右方向鍵調整← →朝向
原理很簡單,如效果圖所示,主要就是以角色視角方向發射大量的直線模擬視線,並計算直線與牆壁交點,獲取每一條視線方向下,角色到牆壁的距離,然後根據近大遠小的原理繪製不同長度的豎向直線模擬牆壁。
第一代程式是使用的polyshape物件(二維多邊形物件)製作牆壁,polyshape物件過載了函數intersect,可以直接求出直線與多邊形的交集,程式編寫更加簡潔方便,給個檢測直線和多邊形交點的官方例子:
建立一個矩形多邊形和一個線段:
poly1=polyshape([0 0 1 1],[1 0 0 1]); lineseg=[-1 -1;1.5 1.5];
計算該多邊形與線段的交集,並確定線段的哪些部分在多邊形的內部,哪些在其外部。
[in,out] = intersect(poly1,lineseg); plot(poly1) hold on plot(in(:,1),in(:,2),'b',out(:,1),out(:,2),'r') legend('Polygon','Inside','Outside','Location','NorthWest')
我們可以把內部第一個點和最後一個點看作與多邊形邊緣的交點:
intersectPnt=[in(1,:);in(end,:)]
intersectPnt =
0 0
1 1
但是!:這樣的計算方法較緩慢,而且polyshape物件推出時間較晚(至少需要R2017B),
於是該方案被捨棄!!
於是該方案被捨棄!!
於是該方案被捨棄!!
假設角色當前位置為p0=(x0, y0) ,角色當前面向方向為θ0,將所有的牆壁邊緣離散成點集合,其點到角色位置方向向量為:
每個視線方向向量
做內積:
那麼INN矩陣的每個數值都是角色到一個牆壁點方向向量與角色某一視線方向做內積,要考慮到視線為單方向射線,因此將內積為負數的值置為無窮大:INN(INN<0)=inf,之後因為明顯和視線越垂直算出的距離越短,但這不是我們想要的,因此要新增新的約束,就是內積值和實際的點到角色的距離差值要小於一定閾值1e-5,新增這個約束後,找到INN矩陣每一列的最小值即可找到每一視線方向最近的牆壁點。
使用的如下公式:
其中α為常數,L為牆壁點到角色距離,θ為視線和角色面朝方向的夾角。
function maze2_5D_v2 % @author : slandarer % @公眾號 : slandarer隨筆 % @知乎 : hikari help maze2_5D %% ======================================================================== % figure視窗建立 fig=figure(); fig.Position=[50,60,1200,600]; fig.Name='maze 2.5D by slandarer'; fig.NumberTitle='off'; fig.MenuBar='none'; % 俯檢視axes座標區域 ax2D=axes('Parent',fig); ax2D.XTick=[];ax2D.XColor='none'; ax2D.YTick=[];ax2D.YColor='none'; ax2D.XLim=[0,15]; ax2D.YLim=[0,15]; ax2D.Color=[0,0,0]; ax2D.Position=[0,0,1/2,1]; hold(ax2D,'on') % 偽3D圖axes座標區域 ax3D=axes('Parent',fig); ax3D.XTick=[];ax2D.XColor='none'; ax3D.YTick=[];ax2D.YColor='none'; ax3D.XLim=[0,10]; ax3D.YLim=[0,10]; ax3D.Color=[0,0,0]; ax3D.Position=[1/2,0,1/2,1]; hold(ax3D,'on') %% ======================================================================== % 左側俯視地圖初始化 mazeMat=[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1; 1 0 0 0 0 0 1 0 1 0 1 0 0 0 1; 1 1 1 1 1 0 1 0 0 0 1 1 1 0 1; 1 0 0 0 1 0 1 0 1 0 1 0 0 0 1; 1 0 1 1 1 0 0 0 1 0 0 0 1 1 1; 1 0 0 0 0 2 1 1 1 0 1 1 1 0 1; 1 0 1 0 1 1 1 0 1 0 0 0 1 0 1; 1 0 1 0 0 0 0 0 1 1 1 0 1 0 1; 1 0 1 1 1 1 1 1 1 0 1 0 0 0 1; 1 0 1 0 0 0 0 0 0 0 1 0 1 0 1; 1 0 1 1 1 1 1 0 1 0 1 0 1 0 1; 1 0 1 0 1 0 1 0 1 0 0 0 1 0 1; 1 0 1 0 1 0 1 0 1 1 1 1 1 0 1; 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1; 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]; [rowList,colList]=find(mazeMat==1); sqX=[-1;0;0;-1];sqY=[-1;-1;0;0]; LSList=linspace(-1,0,250)'; NMList=-ones(size(LSList)); FLList=[[LSList,NMList];[LSList,NMList.*0];[NMList,LSList];[NMList.*0,LSList]]; BLOCK.pntSet=zeros(2,0); for n=1:length(rowList) fill(ax2D,sqX+colList(n),sqY+size(mazeMat,1)+1-rowList(n),[1,1,1].*0.9); BLOCK.pntSet=[BLOCK.pntSet;FLList+repmat([colList(n),size(mazeMat,1)+1-rowList(n)],[size(FLList,1),1])]; end % ------------------------------------------------------------------------- % 角色建立 [trow,tcol]=find(mazeMat==2); ROLEP.xpos=tcol-0.5; ROLEP.ypos=size(mazeMat,1)+0.5-trow; ROLEP.theta=pi/2; ROLEP.triX=cos([pi/3,pi,-pi/3]).*0.15; ROLEP.triY=sin([pi/3,pi,-pi/3]).*0.15; [tX,tY]=rotateData(ROLEP.triX,ROLEP.triY,ROLEP.theta); ROLEP.pfill=fill(ax2D,tX+ROLEP.xpos,tY+ROLEP.ypos,[1,1,1]); ROLEP.pshape=polyshape(tX+ROLEP.xpos,tY+ROLEP.ypos); ROLEP.viewRange=size(mazeMat,1)*sqrt(2); %% ======================================================================== % 線條建立 % plot(ax3D,[1,1].*10.*i./length(thetaListV),[5-tLen/2,5+tLen/2],... % 'LineWidth',1.5,'Color',[1,1,1]./10.*tLen,'Tag','blockLine'); % plot(ax2D,[RP.xpos,RP.xpos+cos(thetaList(i))*abs(minList(i))],[RP.ypos,RP.ypos+sin(thetaList(i))*abs(minList(i))]) lineNum=300; for n=1:lineNum PLINE.plotLine3(n)=plot(ax3D,[1,1].*10.*n./lineNum,[-1,-1],'LineWidth',1.5); PLINE.plotLine2(n)=plot(ax2D,[-1,-1],[-1,-1],'Color',lines(1)); end draw3D(ROLEP,BLOCK,PLINE,lineNum) %% ======================================================================== % 角色移動函數 set(fig,'KeyPressFcn',@key) function key(~,event) %按鍵函數 switch event.Key case 'uparrow' ROLEP.xpos=ROLEP.xpos+cos(ROLEP.theta).*.2; ROLEP.ypos=ROLEP.ypos+sin(ROLEP.theta).*.2; case 'leftarrow' ROLEP.theta=ROLEP.theta+pi/20; case 'rightarrow' ROLEP.theta=ROLEP.theta-pi/20; end [tX,tY]=rotateData(ROLEP.triX,ROLEP.triY,ROLEP.theta); ROLEP.pfill.XData=tX+ROLEP.xpos; ROLEP.pfill.YData=tY+ROLEP.ypos; ROLEP.pshape=polyshape(tX+ROLEP.xpos,tY+ROLEP.ypos); draw3D(ROLEP,BLOCK,PLINE,lineNum) end %% ======================================================================== % 視角檢測及偽3D圖繪製 function draw3D(RP,BK,PLINE,LN) % delete(findobj('Tag','blockLine')) thetaListV=linspace(pi/3,-pi/3,LN); thetaList=thetaListV+RP.theta; % 內積法計算距離 cutoff=1e-5; cosList=cos(thetaList); sinList=sin(thetaList); vecList=BK.pntSet-[RP.xpos,RP.ypos]; disMat=vecList*[cosList;sinList]; disMat(disMat<0)=inf; normList=vecnorm(vecList')'; diffMat=abs(disMat-repmat(normList,[1,size(disMat,2)])); disMat(diffMat>cutoff)=inf; minList=min(abs(disMat)); % 影象重繪 for i=1:length(thetaList) tLen=10/abs(minList(i))/abs(cos(thetaListV(i))).*0.6;tLen(tLen>10)=10; PLINE.plotLine3(i).Color=[1,1,1]./10.*tLen; PLINE.plotLine3(i).YData=[5-tLen/2,5+tLen/2]; PLINE.plotLine2(i).XData=[RP.xpos,RP.xpos+cos(thetaList(i))*abs(minList(i))]; PLINE.plotLine2(i).YData=[RP.ypos,RP.ypos+sin(thetaList(i))*abs(minList(i))]; end end %% ======================================================================== % 資料旋轉角度 function [X,Y]=rotateData(X,Y,theta) rotateMat=[cos(theta),-sin(theta);sin(theta),cos(theta)]; XY=rotateMat*[X;Y]; X=XY(1,:);Y=XY(2,:); end end
以上就是基於Matlab製作偽3D第一視角迷宮小遊戲的詳細內容,更多關於Matlab迷宮遊戲的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45