欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Matlab制作偽3D第一視角迷宮小游戲

 更新時(shí)間:2022年07月06日 15:03:49   作者:slandarer  
這篇文章主要為大家詳細(xì)介紹了如何利用Matlab語(yǔ)言制作偽3D第一視角迷宮小游戲,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以動(dòng)手嘗試一下

游戲效果

使用鍵盤上方向鍵↑向前移動(dòng)

使用鍵盤左右方向鍵調(diào)整← →朝向

游戲原理說(shuō)明

原理很簡(jiǎn)單,如效果圖所示,主要就是以角色視角方向發(fā)射大量的直線模擬視線,并計(jì)算直線與墻壁交點(diǎn),獲取每一條視線方向下,角色到墻壁的距離,然后根據(jù)近大遠(yuǎn)小的原理繪制不同長(zhǎng)度的豎向直線模擬墻壁。

第一代程序計(jì)算交點(diǎn)方法

第一代程序是使用的polyshape對(duì)象(二維多邊形對(duì)象)制作墻壁,polyshape對(duì)象重載了函數(shù)intersect,可以直接求出直線與多邊形的交集,程序編寫更加簡(jiǎn)潔方便,給個(gè)檢測(cè)直線和多邊形交點(diǎn)的官方例子:

創(chuàng)建一個(gè)矩形多邊形和一個(gè)線段:

poly1=polyshape([0 0 1 1],[1 0 0 1]);
lineseg=[-1 -1;1.5 1.5];

計(jì)算該多邊形與線段的交集,并確定線段的哪些部分在多邊形的內(nèi)部,哪些在其外部。

[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')

我們可以把內(nèi)部第一個(gè)點(diǎn)和最后一個(gè)點(diǎn)看作與多邊形邊緣的交點(diǎn):

intersectPnt=[in(1,:);in(end,:)]

intersectPnt =
0 0
1 1

但是?。哼@樣的計(jì)算方法較緩慢,而且polyshape對(duì)象推出時(shí)間較晚(至少需要R2017B),

于是該方案被舍棄??!

于是該方案被舍棄!!

于是該方案被舍棄!!

第二代程序計(jì)算交點(diǎn)方法

假設(shè)角色當(dāng)前位置為p0=(x0, y0) ,角色當(dāng)前面向方向?yàn)?theta;0,將所有的墻壁邊緣離散成點(diǎn)集合,其點(diǎn)到角色位置方向向量為:

每個(gè)視線方向向量

做內(nèi)積:

那么INN矩陣的每個(gè)數(shù)值都是角色到一個(gè)墻壁點(diǎn)方向向量與角色某一視線方向做內(nèi)積,要考慮到視線為單方向射線,因此將內(nèi)積為負(fù)數(shù)的值置為無(wú)窮大:INN(INN<0)=inf,之后因?yàn)槊黠@和視線越垂直算出的距離越短,但這不是我們想要的,因此要添加新的約束,就是內(nèi)積值和實(shí)際的點(diǎn)到角色的距離差值要小于一定閾值1e-5,添加這個(gè)約束后,找到INN矩陣每一列的最小值即可找到每一視線方向最近的墻壁點(diǎn)。

距離轉(zhuǎn)換為線段長(zhǎng)度

使用的如下公式:

其中α為常數(shù),L為墻壁點(diǎn)到角色距離,θ為視線和角色面朝方向的夾角。

完整代碼

function maze2_5D_v2
% @author : slandarer
% @公眾號(hào) : slandarer隨筆
% @知乎   : hikari
help maze2_5D

%% ========================================================================
% figure窗口創(chuàng)建
fig=figure();
fig.Position=[50,60,1200,600];
fig.Name='maze 2.5D by slandarer';
fig.NumberTitle='off';
fig.MenuBar='none';
% 俯視圖axes坐標(biāo)區(qū)域
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坐標(biāo)區(qū)域
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')
%% ========================================================================
% 左側(cè)俯視地圖初始化
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
% -------------------------------------------------------------------------
% 角色創(chuàng)建
[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);
%% ========================================================================
% 線條創(chuàng)建
% 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)
%% ========================================================================
% 角色移動(dòng)函數(shù)
set(fig,'KeyPressFcn',@key)
function key(~,event)
    %按鍵函數(shù)
    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
%% ========================================================================
% 視角檢測(cè)及偽3D圖繪制
    function draw3D(RP,BK,PLINE,LN)
    % delete(findobj('Tag','blockLine'))
    thetaListV=linspace(pi/3,-pi/3,LN);
    thetaList=thetaListV+RP.theta;
    % 內(nèi)積法計(jì)算距離
    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
%% ========================================================================
% 數(shù)據(jù)旋轉(zhuǎn)角度
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第一視角迷宮小游戲的詳細(xì)內(nèi)容,更多關(guān)于Matlab迷宮游戲的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++實(shí)現(xiàn)逆波蘭式

    C++實(shí)現(xiàn)逆波蘭式

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)逆波蘭式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • C++ Boost PointerContainer智能指針詳解

    C++ Boost PointerContainer智能指針詳解

    智能指針是一種像指針的C++對(duì)象,但它能夠在對(duì)象不使用的時(shí)候自己銷毀掉。雖然STL提供了auto_ptr,但是由于不能同容器一起使用(不支持拷貝和賦值操作),因此很少有人使用。它是Boost各組件中,應(yīng)用最為廣泛的一個(gè)
    2022-11-11
  • 初學(xué)C++之自定義類型名簡(jiǎn)化詳解

    初學(xué)C++之自定義類型名簡(jiǎn)化詳解

    下面小編就為就大家?guī)?lái)一篇初學(xué)C++之自定義類型名簡(jiǎn)化詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-09-09
  • 深入二叉樹兩個(gè)結(jié)點(diǎn)的最低共同父結(jié)點(diǎn)的詳解

    深入二叉樹兩個(gè)結(jié)點(diǎn)的最低共同父結(jié)點(diǎn)的詳解

    本篇文章是對(duì)二叉樹兩個(gè)結(jié)點(diǎn)的最低共同父結(jié)點(diǎn)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++如何實(shí)現(xiàn)BCD碼和ASCII碼的相互轉(zhuǎn)換

    C++如何實(shí)現(xiàn)BCD碼和ASCII碼的相互轉(zhuǎn)換

    這篇文章主要介紹了C++實(shí)現(xiàn)BCD碼和ASCII碼互轉(zhuǎn),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • C語(yǔ)言使用libZPlay錄制聲音并寫到文件的方法

    C語(yǔ)言使用libZPlay錄制聲音并寫到文件的方法

    這篇文章主要介紹了C語(yǔ)言使用libZPlay錄制聲音并寫到文件的方法,實(shí)例分析了C語(yǔ)言操作音頻文件的相關(guān)技巧,需要的朋友可以參考下
    2015-06-06
  • MFC實(shí)現(xiàn)在文件尾追加數(shù)據(jù)的方法

    MFC實(shí)現(xiàn)在文件尾追加數(shù)據(jù)的方法

    這篇文章主要介紹了MFC實(shí)現(xiàn)在文件尾追加數(shù)據(jù)的方法,涉及MFC文件操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-09-09
  • mfc入門教程之實(shí)現(xiàn)一個(gè)簡(jiǎn)單的計(jì)算器

    mfc入門教程之實(shí)現(xiàn)一個(gè)簡(jiǎn)單的計(jì)算器

    這篇文章主要介紹了mfc入門教程,手把手教你如何開發(fā)一個(gè)簡(jiǎn)單的計(jì)算器,需要的朋友可以參考下
    2019-04-04
  • C++實(shí)現(xiàn)MyString的示例代碼

    C++實(shí)現(xiàn)MyString的示例代碼

    本文主要介紹了C++實(shí)現(xiàn)MyString的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 在C++中使用HP-Socket

    在C++中使用HP-Socket

    這篇文章主要介紹了C++中簡(jiǎn)單使用HP-Socket,HP-Socket 是一套通用的高性能 TCP/UDP /HTTP 通信 框架 ,包含服務(wù)端組件、客戶端組件和 Agent 組件,廣泛適用于各種不同應(yīng)用場(chǎng)景的 TCP/UDP /HTTP 通信系統(tǒng),下面來(lái)看看更具體的介紹吧
    2021-11-11

最新評(píng)論