Banden - und wie man sie umgeht
Hiermit beginnt unsere Problemreihe! Wir werden im Verlaufe unseres Projektes nach und nach große Probleme, auf die wir gestoßen sind, erläutern und unsere Lösungsansätze darlegen. Heute beschäftigen wir uns mit den Banden. Sie begrenzen das Spielfeld, das von 0 bis 1 sowohl in x-, als auch in y-Richtung verläuft. Somit kann die Bande als solche in 4 Banden unterteilt werden. Linke Bande (x=0), Rechte Bande (x=1), Obere Bande(y=1) und Untere Bande (y=0). Diese Koordinaten darf unser Spaceball nie erreichen, sonst ist das Spiel verloren und wir haben unserem Gegner einen Punkt geschenkt. Das gilt es zu vermeiden! Deshalb werden wir zuerst einen Sicherheitspuffer einbauen, einmal aus Angst, dass unsere Formeln ungenau sind, aber auch aus der Angst vor ungenauen numerischen Ergebnissen Matlabs.
Dieser Sicherheitspuffer beträgt bei uns 0.015.
Theoretisch nähert sich unser Spaceball also nie näher als beispielweise x=0.015 der linken Wand. Wie erreiche ich aber, das er bremst? Wann muss er bremsen? Und muss er immer bremsen? Dafür muss man mehrere Fälle unterscheiden: Fall 1: Der Spaceball fährt in einem nahezu 90° Winkel auf die Wand zu.
Beispiel: auf die linke Wand.
Hierbei handelt es sich um den einfachsten Fall.
Der Spaceball hat nur eine Geschwindigkeitskomponente, die andere ist nahezu null, muss also nicht abgebremst werden. Somit können wir den vollen "Schub" in Gegenrichtung zur Geschwindigkeit geben. Oder in unserem Fall: Vollen Schub von der Wand weg! Wenn unser Spaceball sich auf die linke Wand zubewegt, dann gibt es einen Punkt, ab dem der Spaceball bremsen muss, um nicht innerhalb unserer "Notbremszone (also Wandkoordinate plus Puffer)" zu landen.
Deshalb geben wir für die linke Wand vollen "weg von der Wand Schub" also? Genau, ich.bes=(1,0). Somit erreichen wir, dass die x-Komponente der (noch negativen Geschwindigkeit) einfach weggebremst wird.
Doch woher weiß der Spaceball, dass er zu bremsen hat? Ganz einfach! (Spätestens) Erstes Semester PHYS! s = v^2 / (2*a). Dies ist die Berechnung des Bremsweges, das Ganze wird dann noch mit dem Puffer erweitert und einem Faktor, der uns ermöglicht, dass der Bandenbremsmechanismus früher bremst, als er muss, andere Funktionen aber auch wieder übernehmen können, und wir so zwar bremsen und langsamer werden, aber nicht für die gesamte Dauer des Bremsvorgangs nichts anderes tun können als bremsen. In "Matlab" sieht das dann so aus: ((ich.ges(1)^2)/(0.2)+0.015)*1.3 Wir müssen uns jetzt noch überlegen, wann dieser Mechanismus greifen soll und wenn er gegriffen hat, wie lange, im Falle einer absoluten Notbremsung, die auch eintreten kann, wenn andere Funktionen versagen und zum Beispiel trotz anfänglicher Bremsung wieder auf die Bande zubeschleunigen. Da wir uns in Sachen Banden auf genau 4 Beschleunigungen geeinigt haben, gibt es nur 4 mögliche Beschleunigungen; [1,0] , [-1,0] , [0,1] , [0,-1].
Genauso gibt es auch 4 Fälle, die wir per if-Bedinung eingrenzen müssen: Für die linke Wand wäre das: Wenn mein Bremsweg länger ist, als mein Abstand zur Wand(+Puffer), dann muss ich von der Wand wegbremsen. Also:
if ich.pos(1) <= ((ich.ges(1)^2)/(0.2)+0.015)*1.3
Das wird jetzt noch weiter eingegrenzt, denn wir müssen nur bremsen, wenn unsere Geschwindigkeit kleiner als -0.001 ist. Dies ermöglicht auch, das wir aus der Bedingung ausbrechen können, und nicht weiter von der Wand wegfeuern. Also:
if ich.pos(1) <= ((ich.ges(1)^2)/(0.2)+0.015)*1.3 && ich.ges(1)<-0.001
Dann kommt: bes1 = [+1,0];
Warum bes1? Mehr dazu später.
Fall 2: Der Spaceball fährt in einem flachen Winkel auf die Wand zu.
Beispiel: auf die linke Wand, mit positiver y-Geschwindigkeit.
Dieser Fall ähnelt Fall1, doch wir haben eine nicht zu vernachlässigende Komponente in y-Richtung. Hier greift dennoch nur - und das ist ja auch völlig ausreichend - die Bremsung für die linke Wand und wir können uns unbeschleunigt in y-Komponente weiterbewegen.
auch hier gilt weiterhin:
if ich.pos(1) <= ((ich.ges(1)^2)/(0.2)+0.015)*1.3 && ich.ges(1)<-0.001
bes1 = [+1,0];
Fall 3: Der Spaceball fährt schräg auf eine Ecke zu
Beispiel: auf die obere, linke Ecke.
Hier standen wir vor einem großen Problem! Denn wenn man für beide Wände, wie in der Ecke bremsen muss, dann muss man auch a) mehr Bremsweg in Anspruch nehmen, da der Schubvektor "aufgeteilt" wird und b) muss man dann natürlich auch früher anfangen zu bremsen.
Deswegen haben wir uns dafür entschieden einfach 1+1 zu rechnen.
So werden wir es auch mit den Geschwindigkeiten machen. Der resultierende Vektor rettet uns dann vor dem Einschlag! Genauso sieht es dann auch mit der Mine aus:
Daraus resulitierte dann folgendes Ergebnis:
function Mine (diesetanke) %------------------------------------------------------------------ %-------------------------------Mine------------------------------- %------------------------------------------------------------------ besMine=0; besDMR=0; besDML=0; bestankrich=0; [...] if ~isempty(naechstekollision) %Überprüfen ob Kollisionsmatrix leer ist length(naechstekollision); %Anzahl der zu kollidierenden Minen [M,I] = min([naechstekollision.abstand]); %Angabe der dichtesten Mine besMine=ich.pos-naechstekollision(I).pos; %Beschleunigung entgegen der Minenrichtung if display == true disp('Weg von der Mine') end %Angabe der Beschleunigung entgegen der Minenrichtung sb = norm(ich.ges)^2/(2*spiel.bes) + ich.ges/norm(ich.ges); %Formel des Bremsweges plus der Geschwindigkeitsrichtung pos = ich.pos + sb; %Position inklusive Bremsweg ab = norm(naechstekollision(I).pos - ich.pos) + ... spiel.mine_radius + ich.radius; %Abstand zur Mine plus Summe der Radien tankrich = diesetanke - ich.pos; %Richtung zur nächsten Tanke if ab < 0.01 %Wenn der Abstand zur Mine kleiner als 0.01 ist, dann... bestankrich = tankrich; %...beschleunigen wir in Richtung der nächsten Tanke, um %ihn in Bewegung zu halten if display == true disp('tankrich') end %Angabe der Beschleunigung in Richtung der Tankrichtung end if norm(ich.ges) < 10^-1.25 %Wenn der Betrag unserer Geschwindigkeit kleiner als %10^-1.25 ist, dann... if (ich.pos(2)-diesetanke(2))* ... (naechstekollision(I).pos(1)-diesetanke(1))- ... (naechstekollision(I).pos(2)-diesetanke(2))* ... (ich.pos(1)-diesetanke(1)) >0 %Wenn der Vektor Mine/Tanke links vom Vektor %Wir/Tanke liegt (y2*x1-y1*x2>0), dann... besDMR = (ich.pos-naechstekollision(I).pos) * ... [0,1;-1,0] + (ich.pos-naechstekollision(I).pos); %...drehen wir rechts um die Mine mittles einer %Drehmatrix if display == true disp('mit rechter Drehmatrix') end %Angabe, dass wir mit rechter Drehmatrix drehen else besDML = (ich.pos-naechstekollision(I).pos) * ... [0,-1;1,0] + (ich.pos-naechstekollision(I).pos); %...drehen wir links um die Mine mittels einer %Drehmatrix if display == true disp('mit linker Drehmatrix') end %Angabe, dass wir entgegen der Mine mit einer Drehung %der Beschleunigungsrichtung um 90 Grad (Drehmatrix) %beschleunigen end end end %------------------------------------------------------------------ %----------WAND PROTECTION /// ECKEN PROTECTION-------------------- %------------------------------------------------------------------ % Linke Wand bes1=0; ((ich.ges(1)^2)/(0.2)+0.015); if ich.pos(1) <= ((ich.ges(1)^2)/(0.2)+0.015)*1.3 && ... ich.ges(1)<-0.001 bes1 = [+1,0]; if display == true disp('Linke Wand') end end bes2=0; % Obere Wand if 1-ich.pos(2) <= ((ich.ges(2)^2)/(0.2)+0.015)*1.3 && ... ich.ges(2)>0.001 bes2 = [0,-1]; if display == true disp('Obere Wand') end end % Rechte Wand bes3=0; if 1-ich.pos(1) <= ((ich.ges(1)^2)/(0.2)+0.015)*1.3 && ... ich.ges(1)>0.001 bes3 = [-1,0]; if display == true disp('Rechte Wand') end end bes4=0; % Untere Wand if ich.pos(2) <= ((ich.ges(2)^2)/(0.2)+0.015)*1.3 && ... ich.ges(2)<-0.001 bes4 = [0,1]; if display == true disp('Untere Wand') end end if norm(bes1) ~= 0 || norm(bes2) ~= 0 || norm(bes3) ~= 0 || ... norm(bes4) ~= 0 || norm(besMine) ~= 0 ||... norm(besDML) ~= 0 || norm(besDMR) ~= 0 ||... norm(bestankrich) ~= 0 bes=bes1+bes2+bes3+bes4+besMine+besDML+besDMR+bestankrich; end %---------------------------------------------------------- %-------------------------Ende----------------------------- %---------------------------------------------------------- end
Gern geschehen.