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
Cite As
Hernia Baby (2024). FPS_Sample (https://www.mathworks.com/matlabcentral/fileexchange/111640-fps_sample), MATLAB Central File Exchange. Retrieved .
MATLAB Release Compatibility
Created with
R2022a
Compatible with any release
Platform Compatibility
Windows macOS LinuxTags
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!Discover Live Editor
Create scripts with code, output, and formatted text in a single executable document.
Version | Published | Release Notes | |
---|---|---|---|
1.0.0 |