billiard animation, set multiple rectangles, funny guy

2 vues (au cours des 30 derniers jours)
Ansgar Elles
Ansgar Elles le 20 Fév 2021
Réponse apportée : darova le 20 Fév 2021
Hi everyone!
Im calculating the movement of billiardballs on a table. The calculations work I think but im having problems with the animation. I cant get the programm to show the desired number of balls at the same time(/in the same frame). The set function always replaces the previously placed ball. Hold on doesnt work.
I preallocated the number of balls(/rectangles) with gobjects. Please help, Im at the end of my latin. Sorry my english is not the yellow from the egg.
global m d r endvelocity num_balls
m=0.17; d=0.15; r=0.04;%0.0285 %; %mass, friction, radius
tspan = 0:0.0025:10;
while_counter = 1; %while loop counter
% for_counter = 1;
stillrolling = 1; % while loop, entry value
endvelocity = 0.1; % end speed at which simulation stops
options = odeset('AbsTol',1e-10,'RelTol',1e-8,'Events', @event_collision_more_balls); %,'AbsTol',1e-10, 'RelTol',1e-8
% set parameters for balls
%known maximum speed of balls is up to 14 meters per second (in real billiard tournaments)
num_balls = 3;
num_variables = num_balls*4; %num_balls now actually refers to the number of kinematic variables
vals_blueball = [0.1 0 2 1]; %[sx vx sy vy]
vals_redball = [0.3 0 3 1];
vals_cyanball = [0.5 0 2 1];
vals_magentaball = [0.5 0 2 1];
vals_yellowball = [1 0 2 1];
vals_blackball = [1.2 0 2 1];
vals_whiteball = [1.4 0 2 1];
vals_balls = [vals_blueball,vals_redball,vals_cyanball,vals_magentaball,vals_yellowball,vals_blackball,vals_whiteball]; %[sx1 vx1 sy1 vy1 sx2 vx2 sy2 vy2]
vals_balls = vals_balls(1:num_variables); %pick the chosen number of values
figure('NumberTitle','Off','Name','elastic_collision');
axis([0 1.78 0 3.57]); axis equal; %Frage: Bringt hier "hold on" etwas?
title('Billiard table');
playingfield = rectangle('Position',[0 0 1.78 3.57],'FaceColor','g');
ballsack = gobjects(1,num_balls);
ballsack(:,:) = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','r');
%redball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','r');
%up to 7 balls
% blueball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','b');
% redball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','r');
% cyanball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','c');
% magentaball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','m');
% yellowball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','y');
% blackball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','k');
% whiteball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','w');
%initiate place holder/adress
t_total = zeros(1,1);
y_total = zeros(1,num_variables);
%% While loop
while stillrolling == 1
[t,y,te,ye,ie] = ode45(@kinematics_more_balls,tspan,vals_balls,options);
if ismember(ie,1:num_balls) %left border
vals_balls = y(end,:);
vector = 2:4:num_variables;
idx = vector(ie);
vals_balls(1,idx) = -vals_balls(1,idx);
elseif ismember(ie,num_balls+1:num_balls*2) %right border
ie = ie - num_balls;
vals_balls = y(end,:);
vector = 2:4:num_variables;
idx = vector(ie);
vals_balls(1,idx) = -vals_balls(1,idx);
elseif ismember(ie,num_balls*2+1:num_balls*3) %top border
ie = ie - num_balls*2;
vector = 4:4:num_variables;
idx = vector(ie);
vals_balls(1,idx) = -vals_balls(1,idx);
elseif ismember(ie,num_balls*3+1:num_balls*4) %bottom border
ie = ie - num_balls*3;
vector = 4:4:num_variables;
idx = vector(ie);
vals_balls(1,idx) = -vals_balls(1,idx);
elseif ie == num_balls*4+num_balls*(num_balls-1)/2+1
disp('Die Kugeln rollen nicht mehr.')
stillrolling = 0;
end
t_total = [t_total; t];
y_total = [y_total; y];
while_counter = while_counter+1;
end
hold on
for k1 = 2:length(t_total)
prop_name = {'Position'};
prop_value = {'[y_total(k1,1:4:end)-r; y_total(k1,3:4:end)-r; ones(1,num_balls)*2*r; ones(1,num_balls)*2*r]'};
set(ballsack,prop_name,prop_value)
drawnow
end
function kinematics = kinematics_more_balls(t,y)
global m d num_balls
kinematics = ones(4*num_balls,1);
%kinematics = [y(2), -d/m*y(2), y(4), -d/m*y(4), y(6), -d/m*y(6), y(8), -d/m*y(8)]';
%connection_monitor = sqrt((y(5)-y(1))^2 + ((y(7)-y(3))^2)) - 2*r
%[sx1 vx1 sy1 vy1 sx2 vx2 sy2 vy2 ...]
kinematics(1:4:end) = y(2:4:end);
kinematics(2:4:end) = -d/m*y(2:4:end);
kinematics(3:4:end) = y(4:4:end);
kinematics(4:4:end) = -d/m*y(4:4:end);
end
function [value,isterminal,direction] = event_collision_more_balls(t,y)
%event-Funktion beendet Integration sobald einer der Werte in "value" null
%wird (entspricht Beruehrung der Bande, siehe "isterminal" ==1 d.h. Terminierung auf "true").
global r endvelocity
%with n being the number of balls -1
value = [-y(1:4:end)'+r, y(1:4:end)'+r-1.78, y(3:4:end)'+r-3.57, -y(3:4:end)'+r, -pdist([y(1:4:end),y(3:4:end)]) + 2*r, -max(sqrt((y(2:4:end)).^2 + (y(4:4:end)).^2)) + endvelocity]; %wird negativ, wird negativ, wird positiv, wird positiv (bei verlassen des Spielfeldes)
isterminal = ones(1,length(value)); %2 balls = 10 values
direction = ones(1,length(value)); %"+1" = triggered when event-function is increasing, "-1" when decreasing, "0" = consider both
% connections = pdist([y(1:4:end),y(3:4:end)]);
% %connections is a n*(n+1)/2 dimensional row-vector
end

Réponses (1)

darova
darova le 20 Fév 2021
Here is an example
clc,clear
g = 9.8;
n = 3;
x0 = rand(n,1);
y0 = rand(n,1);
vx = rand(n,1);
vy = rand(n,1);
dt = 0.03;
cla
plot([0 1 1 0 0],[0 0 1 1 0])
hold on
for i = 1:100
x1 = x0 + vx*dt;
y1 = y0 + vy*dt;
sx = 0<x1 & x1<1; % inside the rectangle?
sy = 0<y1 & y1<1;
y1 = y1 + (y1<0)*dt.*vy/5; % correction if bottom border
vx = sign(sx-0.5).*vx;
vy = sign(sy-0.5).*vy - g*dt;
plot([x0 x1]',[y0 y1]','.-r')
x0 = x1;
y0 = y1;
pause(0.1)
end
hold off

Catégories

En savoir plus sur Specifying Target for Graphics Output dans Help Center et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by