If you want to change the wall, you can change pos_wall parameter.
function test_FPS
clear,clc,close all;
m=200;
% Wall Samples
% pos_wall = [50 50; 100 300; 250 200; 50 50]+100;
p = nsidedpoly(50, 'Center', [200 200], 'Radius', 100);
pos_wall = [p.Vertices;p.Vertices(1,:)];
% Player 1st position
player.pos = [10,10];
player.angle = 45;
Angle = 30;
dAngle = 10;
n = 21;
% Generate an arc and line segments
th = deg2rad(linspace(player.angle - Angle,player.angle + Angle,n))';
r = 100;
v = r.*[cos(th),sin(th)];
p2 = v + player.pos;
% Intersection calculation(1st step)
% Mapping Toolbox --> polyxpoly
% Free: https://jp.mathworks.com/matlabcentral/fileexchange/22441-curve-intersections
x = reshape(([repelem(player.pos(1),height(p2))',p2(:,1),nan(height(p2),1) ])',[],1);
y = reshape(([repelem(player.pos(2),height(p2))',p2(:,2),nan(height(p2),1) ])',[],1);
[xi,yi,kk] = polyxpoly(x,y,pos_wall(:,1),pos_wall(:,2));
% Wall for Bird's eye view
Wallx = (1:height(p2))';
% Calculate only in front
dummy = Wallx.*(4-1) + 1;
dummy = [1 ; dummy(1:end-1)];
Wally = nan(height(p2),1);
th2 = -deg2rad(linspace(-Angle,Angle,n))';
K = 3; % Fix parameter: 4-1
%% Plot
%% 1. Bird's eye view
f = figure('Color','#AAAAAA');
ax = axes('Color','#AAAAAA');
ax.Title.String = "Bird's eye view";
text(350,350,["r:ClockWise";"e:CounterClockWise";"a:ZoomIn";"s:ZoomOut"]);
axis off
hold on
% Wall
wall = fill(ax,pos_wall(:,1),pos_wall(:,2),'k',LineStyle='none');
axis equal
ax.XLim = [0 400];
ax.YLim = [0 400];
% Player1: Position
pl = plot(ax,player.pos(1), player.pos(2),'o', ...
MarkerFaceColor='y',MarkerEdgeColor='none',...
MarkerSize=5);
% Player2: Arc
pl1 = plot(ax,p2(:,1),p2(:,2),'LineStyle','-', ...
'LineWidth',1,'Color','y');
% Player3: Line segments
for ii = 1:height(p2)
pl2(ii) = plot(ax,[player.pos(1);p2(ii,1)],...
[player.pos(2); p2(ii,2)],'LineStyle','--', ...
'LineWidth',1,'Color','y');
end
tmp1 = [xi;nan(height(p2)-length(xi),1)]';
tmp2 = [yi;nan(height(p2)-length(yi),1)]';
% Collision detection
pl3 = plot(ax,tmp1,tmp2,'o', ...
LineStyle='none', ...
MarkerFaceColor='r',MarkerEdgeColor='none',...
MarkerSize=5);
hold off
%% 2. First person perspective
f_FPS = figure('Color','#AAAAAA');
ax_FPS = axes('Color','#AAAAAA');
ax_FPS.Title.String = "First person perspective";
hold on
pl_FPS_p = stem(ax_FPS,-Wallx,Wally./2,'Marker','none','LineWidth',round(m/n),'Color','w');
pl_FPS_n = stem(ax_FPS,-Wallx,-Wally./2,'Marker','none','LineWidth',round(m/n),'Color','w');
ax_FPS.XLim = [-(height(Wallx)+1) 0];
% Wall Max Height
ax_FPS.YLim = [-1 1].*K*2;
% Visualise
ax_FPS.XTick = [];
ax_FPS.YTick = [];
ax_FPS.XAxis.Color = 'none';
ax_FPS.YAxis.Color = 'none';
hold off
%% Trigger
f.WindowButtonDownFcn = @motion;
f.WindowButtonUpFcn = @motion;
f.KeyPressFcn = @rotation;
%% Nested function
%% Rotation
function rotation(src,data,eventdata)
if strcmp(data.Key,'r')
th = th + deg2rad(dAngle);
elseif strcmp(data.Key,'e')
th = th - deg2rad(dAngle);
end
if strcmp(data.Key,'a')
r = r + 10;
elseif strcmp(data.Key,'s')
r = r - 10;
end
v = r*[cos(th),sin(th)];
movepoint;
end
%% Mouse Click
function motion(src,data,eventdata)
if strcmp(data.EventName,'WindowMousePress')
f.WindowButtonMotionFcn = @movepoint;
else
f.WindowButtonMotionFcn = '';
end
end
%% Position update
function movepoint(src,data)
pos = get(gca,'CurrentPoint');
pl.XData = pos(1,1);
pl.YData = pos(1,2);
pl1.XData = v(:,1) + pl.XData;
pl1.YData = v(:,2) + pl.YData;
player.pos = pos(1,1:2);
p2 = [pl1.XData; pl1.YData]';
Cross;
for ii = 1:length(pl2)
pl2(ii).XData = [0, v(ii,1)] + pl.XData;
pl2(ii).YData = [0, v(ii,2)] + pl.YData;
end
end
%% Collision detection
function Cross
x = reshape(([repelem(player.pos(1),height(p2))',p2(:,1),nan(height(p2),1) ])',[],1);
y = reshape(([repelem(player.pos(2),height(p2))',p2(:,2),nan(height(p2),1) ])',[],1);
[xi,yi,kk] = polyxpoly(x,y,pos_wall(:,1),pos_wall(:,2));
% Vector from plyer to cross point
tmp = [xi,yi] - player.pos;
% extract more closer point when line segment has 2 cross points
tmp = [xi, yi, (tmp(:,1).^2+tmp(:,2).^2), kk(:,1), false(length(xi),1)];
t1 = unique(tmp(:,4));
for jj = 1:length(t1)
MIN_tmp = min(tmp(tmp(:,4) == t1(jj),3));
tmp( (tmp(:,4)==t1(jj)) & (tmp(:,3)==MIN_tmp) ,end) = true;
end
% point y
idx = tmp(:,end)==true;
% extract xi and yi
tmp = tmp(idx,[1:4]);
[~,I] = sort(tmp(:,4));
tmp = tmp(I,:);
xi = tmp(:,1);
yi = tmp(:,2);
idx2 = ismember(dummy,tmp(:,4));
Wallx = (1:height(p2))';
Wally = nan(height(p2),1);
Wally(find(idx2)) = sqrt(tmp(:,3)./r.^2); %norm length
Wally = Wally.*cos(th2);
pl_FPS_p.YData = K./Wally./2;
pl_FPS_n.YData = -K./Wally./2;
pl3.XData = [xi;nan(height(p2)-length(xi),1)]';
pl3.YData = [yi;nan(height(p2)-length(yi),1)]';
end
end
Zitieren als
Hernia Baby (2025). FPS_Sample (https://www.mathworks.com/matlabcentral/fileexchange/111640-fps_sample), MATLAB Central File Exchange. Abgerufen.
Kompatibilität der MATLAB-Version
Erstellt mit
R2022a
Kompatibel mit allen Versionen
Plattform-Kompatibilität
Windows macOS LinuxTags
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!Live Editor erkunden
Erstellen Sie Skripte mit Code, Ausgabe und formatiertem Text in einem einzigen ausführbaren Dokument.
Version | Veröffentlicht | Versionshinweise | |
---|---|---|---|
1.0.0 |