How to generate rectangles based on coordinates in a randomized matrix?
14 ビュー (過去 30 日間)
古いコメントを表示
So I have a matrix. Currently it looks like this:
S.matrix =
2 78 46
1 148 148
3 431 431
1 224 224
1 595 595
3 58 58
1 160 160
1 244 244
1 410 410
1 526 526
Now I have code that makes this matrix random, meaning the numbers are all random (as long as they are between 1 and 640) as well as the size. The amount of columns stay the same, but the rows are not set. My current code has it that as longs as a certain condition is fulfilled, a new row to the matrix is added, hence the ambigous size. For the sake of debugging, I set the condition to a certain point such that the code will always produce a 3x10 matrix.
if S.matrix(:,1) == 1
S.blasterEM = rectangle("Position",[S.matrix(:,2) S.matrix(:,3) 5 10]);
S.blasterEM.FaceColor = [1 0 0];
S.blasterEM.EdgeColor = NA;
elseif S.matrix(:,1) == 2
S.sniperEM = rectangle("Position",[S.matrix(:,2) S.matrix(:,3) 5 15]);
S.sniperEM.FaceColor = [1 0 1];
S.sniperEM.EdgeColor = NA;
elseif S.matrix(:,1) == 3
S.chaserEM = rectangle("Position",[S.matrix(:,2) S.matrix(:,3) 5 20]);
S.chaserEM.FaceColor = [0 1 0];
S.chaserEM.EdgeColor = NA;
end
This code runs if statements depending on the first column and is supposed to produce rectangels according to the corresponding row. For example, S.matrix(1,1) will produce a specific type of rectangle at coordinates (78, 46). However, not only are the rectangles not showing up in the figure, I believe the rectangles aren't being produced at all. Is there a way I can make the if statements more precise such that any time the column at S.matrix(:,1) fulfills the parameters of the if statement, it will produce a rectangle at the corresponding coordinates? I also want to be able to make it so that the it will produce rectangles no matter the N of a 3xN matrix.
Any help is appreciated. Sorry if my problems seems a bit confusing to understand. Comment any misunderstandings, and I will do my best to answer.
0 件のコメント
採用された回答
Voss
2022 年 4 月 29 日
編集済み: Voss
2022 年 4 月 29 日
S.matrix(:,1) is a vector, so S.matrix(:,1) == 1 is a vector (of class logical) the same size as S.matrix(:,1). When that vector is used as a condition in an if statement, it's considered true (i.e., the code inside if block executes) only if all of that vector's elements are true.
In this case S.matrix(:,1) is not all 1's and it's not all 2's and it's not all 3's, so none of those if/elseif conditions are considered true, so no rectangles are created.
There are different ways to create those rectangles and store them. Here's one way, in which S.blasterEM, S.sniperEM and S.chaserEM are all arrays of rectangles (because in general there can be more than one rectangle of each type). The logic here is the same as yours, but within a for loop where each element of S.matrix(:,1) is checked separately and a new rectangle of the appropriate type is created and added to the appropriate array of rectangles.
(I assumed NA meant "none", since it wasn't defined.)
S.matrix = [
2 78 46
1 148 148
3 431 431
1 224 224
1 595 595
3 58 58
1 160 160
1 244 244
1 410 410
1 526 526
];
S.blasterEM = [];
S.sniperEM = [];
S.chaserEM = [];
for ii = 1:size(S.matrix,1)
if S.matrix(ii,1) == 1
S.blasterEM(end+1) = rectangle( ...
"Position",[S.matrix(ii,2) S.matrix(ii,3) 5 10], ...
"FaceColor",[1 0 0], ...
"EdgeColor","none"); % specify the properties when the rectangle is created ...
elseif S.matrix(ii,1) == 2
S.sniperEM(end+1) = rectangle("Position",[S.matrix(ii,2) S.matrix(ii,3) 5 15]);
set(S.sniperEM(end),'FaceColor',[1 0 1]); % ... or set() the properties afterward
set(S.sniperEM(end),'EdgeColor',"none");
elseif S.matrix(ii,1) == 3
S.chaserEM(end+1) = rectangle( ...
"Position",[S.matrix(ii,2) S.matrix(ii,3) 5 20], ...
"FaceColor",[0 1 0], ...
"EdgeColor","none");
end
end
8 件のコメント
Voss
2022 年 4 月 29 日
Here's a working program that does the ship and chaser movement. You can run it on its own, and also take the parts you need (particularly from fig_kpfcn) into your own program. I had to make assumptions about the structure of the program (here I'm using nested functions, for instance), so you may have to make appropriate modifications to the parts you use.
Note that this updates the chasers' rectangles directly, rather than updating S.matrix, but you can modify it to update S.matrix and then update the rectangles from that, if that's necessary.
function main_game()
%creates parameters for ship
xCenter = 320;
yCenter = 320;
radius = 20;
j = 1;
figure('KeyPressFcn',@fig_kpfcn);
S = struct( ...
'ship',circle(xCenter,yCenter,radius));
S.matrix = [
2 78 46
1 148 148
3 431 431
1 224 224
1 595 595
3 58 58
1 160 160
1 244 244
1 410 410
1 526 526
];
S.blasterEM = [];
S.sniperEM = [];
S.chaserEM = [];
for ii = 1:size(S.matrix,1)
if S.matrix(ii,1) == 1
S.blasterEM(end+1) = rectangle( ...
'Position',[S.matrix(ii,2) S.matrix(ii,3) 5 10], ...
'FaceColor',[1 0 0], ...
'EdgeColor','none');
elseif S.matrix(ii,1) == 2
S.sniperEM(end+1) = rectangle( ...
'Position',[S.matrix(ii,2) S.matrix(ii,3) 5 15], ...
'FaceColor',[1 0 1], ...
'EdgeColor','none');
elseif S.matrix(ii,1) == 3
S.chaserEM(end+1) = rectangle( ...
'Position',[S.matrix(ii,2) S.matrix(ii,3) 5 20], ...
'FaceColor',[0 1 0], ...
'EdgeColor','none');
end
end
function h = circle(xCenter,yCenter,radius)
% function that makes the ship
hold on
th = 0:pi/50:2*pi;
xunit = radius * cos(th) + xCenter;
yunit = radius * sin(th) + yCenter;
h = plot(xunit, yunit, 'Color', 'c', 'LineWidth', 2);
hold off
end
function [] = fig_kpfcn(~,E)
%function that corresponds to key press
if j == 1
switch E.Key
case 'rightarrow'
set(S.ship,'XData',get(S.ship,'XData')+3);
xCenter = xCenter+3;
case 'leftarrow'
set(S.ship,'XData',get(S.ship,'XData')-3);
xCenter = xCenter-3;
case 'uparrow'
set(S.ship,'YData',get(S.ship,'YData')+3);
yCenter = yCenter+3;
case 'downarrow'
set(S.ship,'YData',get(S.ship,'YData')-3);
yCenter = yCenter-3;
otherwise
% return if another key was pressed, so that the code
% below doesn't run if the ship didn't move
return
end
% makePoints() % not sure what this does or where it should be
% relative to the rest of the code I'm putting here
if ~isempty(S.chaserEM)
% get chasers' centers:
pos = get(S.chaserEM,'Position');
if iscell(pos)
pos = vertcat(pos{:});
end
rec_centers = pos(:,[1 2])+pos(:,[3 4])/2;
% calculate vectors between ship_center and rec_centers:
v_centers = rec_centers-[xCenter yCenter];
% calculate distances between ship_center and rec_centers:
d_centers = sqrt(sum(v_centers.^2,2));
% move chasers closer to ship center by 4 units:
% first set the new distances (use max(0,__) so the chasers
% don't cross the ship center)
d_centers = max(0,d_centers-4);
% get the direction of each chaser from the ship
v_angles = atan2(v_centers(:,2),v_centers(:,1));
% get the new chaser centers by calculating the points along
% those directions, d_centers away from the ship
v_centers = [xCenter yCenter]+d_centers.*[cos(v_angles) sin(v_angles)];
% set the lower-left corners of the chasers
pos(:,[1 2]) = v_centers-pos(:,[3 4])/2;
% update the chaser Positions
for ii = 1:numel(S.chaserEM)
set(S.chaserEM(ii),'Position',pos(ii,:));
end
% handle rec_centers less than 3 units of [xCenter yCenter]:
idx = d_centers < 3;
if any(idx)
% delete the successful kamikaze chasers
delete(S.chaserEM(idx));
% remove the dead rectangles from the array
S.chaserEM(idx) = [];
% decrement the ship's lives by 1, or by nnz(idx) if each kamikaze
% chaser that gets within 3 units contributes a 1-life decrement:
% TBD (I don't know what variable in your code this would be)
% if ship has no remaining lives, do something special I assume
end
end
end
end
end
その他の回答 (0 件)
参考
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
