Kollision zwischen Kugel und Balken

NetPerformance

Erfahrenes Mitglied
Hi,

ich versuche Arkanoid zu programmieren.
Wenn ich die Kugel mehrmals quer gegen die unteren Balken spiele, fliegt die Kugel durch die Balken !
Ich kann mir das leider nicht erklären.

Den Quelltext habe ich mir aus den verschiedenen Foren zusammengesucht.

Bis auf diese Parameter habe ich alles verstanden.
Da ich das Problem in den anderen Zeilen nicht entdecken kann, gehe ich davon aus, dass diese Zeilen den Fehler verursachen.

_x += Math.sin(Math.PI/180*winkel)*speed;
_y -= Math.cos(Math.PI/180*winkel)*speed;

Zusätzlich zum Hauptproblem würde ich gerne wissen, ob es eine elegantere Lösung zum erstellen der Blöcke gibt. Ich könnte die Blöcke durch eine Schleide auf die Ebene anordnen. Das meine ich nicht mit schöner..
Ich würde gerne nur ein "Block" mc erstellen und irgendwie per AS die "farb" Ebene verändern. Wie kann ich mein Vorhaben umsetzen.

Dank und Gruß im Vorraus
Aaron
 

Anhänge

  • 3.zip
    3.zip
    13,4 KB · Aufrufe: 29
Hi Aaron,

ich bin zwar kein Profi auf dem Gebiet, allerdings würde ich Pauschal sagen, dass diese Anweisungen die Berechnungen sind, mit welchem der Kugel, der Ausfallwinkel anhand des Einfallswinkel übergeben werden. Sprich: Umso flacher die Kugel gegen den Balken "prallt", desto flacher der Winkel, in dem sie den Balken wieder verlässt.

Wenn die Kugel allerdings durch den Balken fliegt, kann es evtl. sein, dass ein Fehler in der Funktion hitTest() aufgetreten ist, bzw. diese Funktion nicht geladen wird.

Mehr kann ich im Moment auch noch nicht dazu sagen.
Ich werde mir aber die Angehängte Datei nochmal in Ruhe zu Gemüte führen, in der Hoffnung, dir doch noch irgendwie helfen zu können.

Bis dahin viel Spaß.

Gruß,

.

PS: Vieleicht hat ja auch schon ein anderes "Genie" eine Idee ;)
 
Hi,

diese beiden Zeilen verwenden Polare Angaben (Winkel, Geschwindigkeit), um einen kartesischen Vektor für die Bewegung zu erhalten. Das hat mit der Kollision nichts zu tun.

Ich bin hier grade am rumprobieren und poste nachher einen Vorschlag für die Kollision.

Zum Anordnen der Steine kann ich jetzt schon was sagen: In meiner Testdatei gibt es eine XML-Datei, die in etwa so ausschaut:
Code:
<row bricks="0,1,1,2,2,0,0,2,2,1,1,0" />
<row bricks="0,1,2,2,0,0,0,0,2,2,1,0" />
<row bricks="3,3,0,0,1,1,1,1,0,0,3,3" />
<row bricks="0,3,2,1,0,3,3,0,1,2,3,0" />
<row bricks="2,2,2,0,0,1,1,0,0,2,2,2" />
Pro Steinreihe eine Zeile, Pro Stein eine Ziffer. 0 bedeutet: kein Stein, die anderen Zahlen stehen für verschiedene Farben.

Und so kann man damit prima einige Steine anordnen:
PHP:
var xm = new XML();
xm.ignoreWhite = true;
xm.onLoad = function() {
	parse(this);
}

var brick = new Array();
var running = 0;

xm.load("level1.xml");

function parse(obj) {
	for (var i=0; i<obj.childNodes.length; i++) {
		var row = obj.childNodes[i].attributes.bricks;
		for (var h=0; h<12; h++) {
			var v = row.substr(h * 2, 1);
			if (v != "0") {
				brick[running] = field.attachMovie("brick", "brick" + running, running);
				brick[running].bmode = parseInt(v, 10);
				// bmode = Farbwert
				brick[running]._x = h * 45;
				brick[running]._y = i * 16;
				running ++;
			}
		}
	}
	go();
}
Der MovieClip "brick" checkt nun seine Membervariable "bmode" selbst und ändert entsprechend seinen Hintergrund.

Gruß
.
 
Hi..


@Datic:
Danke für dein Beitrag:
Werde mir dein Vorschlag gleich in ruhe testen..
wollte nur mal schnelle den Lösungsvorschlag posten ..

Habe hier eine Lösung erhalten:
Das Ganze funktioniert, solange ich die farbigen Blöcke noch nicht getroffen habe :(
Aussedem funktioniert der Vorschlag nicht wenn ich 2 Blöcke gleichzeitig treffe !

------

Der Fehler tritt auf wenn der Ball zwei Balken gleichzeitig trifft. Der eine Balken schickt den Ball dann nach unten und der andere Balken setzt ihn wieder in die andere Richtung.

Das Problem lässt sich durch eine kontroll Variable umgehen:

Auf Block:
Code:
// Für die grauen Balken:
onClipEvent (enterFrame) {
    if (hitTest(_root.ball) && _root.go == false) {
        _root.ball.winkel += ((180-_root.ball.winkel)-90)*2;
        _root.go = true;
    }
}

Auf Pad:
Code:
if (hitTest(_root.pad)) {
        _root.go = false;
        // _x -> Ball Position
        // _pad._x
        dif = int(_x-_root.pad._x);
        winkel += (((180-winkel)-90)*2)+dif;
    }

Auf root:
go = false;

Lösungsvorschlag von :
Sebastian Wichmann


Gruß
Aaron
 
Zuletzt bearbeitet:
Hi,

ich bin mir nicht ganz sicher, ob dieser Lösungsvorschlag funktioniert: Wie ich das sehe, kann dann der Ball dann nur wieder von einem Stein abprallen, wenn er das nächste Mal den Schläger berührt hat?

Hmm... anbei mal eine Variante von mir, obwohl auch die noch nicht fehlerfrei funktioniert (siehe Anhang).

Was ich mache, ist, dass ich wie gehabt meine Polarkoordinaten in einen kartesischen Vektor umwandele (winkel und Geschwindigkeit nach dx und dy) und schaue, ob mich die nächste Bewegung in einen Stein tragen wird. Ist das Der Fall, teste ich den Schnittpunkt des Vektors Momentane Position -> nächste Position mit den beiden senkrechten Kanten des Steins. Liegt dieser Schnittpunkt innerhalb des Höhenbereichs des Steins, so habe ich ihn von der Seite getroffen und lasse den Ball zu den Seiten abprallen (durch Negierung des horizontalen Vektorwertes), ansonsten nach oben bzw. unten.

Auch hierbei gibt es Probleme, wenn der Ball in einem Abwasch mehrere Steine treffen würde, oder nur die Ecke eines Steines schneidet, aber ich arbeite daran. ;)

Gruß

P.S.: Zur Verdeutlichung lasse ich die Vektoren bei Kollision einzeichnen: Grün = Oben/Unten, Gelb = Links/Rechts
.
 

Anhänge

@Datic: Der Lösungsvorschlag von Sebastian funktioniert wie du bereits bemerkt hast überhaupt nicht :)

Ich habe angefangen dein Programm zu verstehen.

Code:
// XML Objekt wird erzeugt
var xm = new XML();

// Leerzeilen und Tabs werden ignoriert
xm.ignoreWhite = true;

// XML wird durch diese Methode geladen
xm.onLoad = function() 
{
	parse(this);
}

// Array
var brick = new Array();

var running = 0;

// level1.xml wird geladen
xm.load("level1.xml");
/*
<row bricks="0,1,1,2,2,0,0,2,2,1,1,0" />
<row bricks="0,1,2,2,0,0,0,0,2,2,1,0" />
<row bricks="3,3,0,0,1,1,1,1,0,0,3,3" />
<row bricks="0,3,2,1,0,3,3,0,1,2,3,0" />
<row bricks="2,2,2,0,0,1,1,0,0,2,2,2" />
*/

// Methode verarbeitet die XML Datei
function parse(obj) 
{
	// childNodes: ist ein Array mit Verweis auf unterknoten
	// von 0 bis ende des Arrays werden alle Unterknoten durchlaufen ->
	// Jedes der Unterknoten beinhaltet 12 Blöcke
	// Hier werden die Zeilen durchlaufen
	for (var i=0; i<obj.childNodes.length; i++) 
	{
		// Die erste bzw. 0te Zeile des Arrays wird in row geschrieben -> row wird 12x überschrieben
		var row = obj.childNodes[i].attributes.bricks;
		
		// h=12 == Zeilenlänge des Arrays 
		// Hier werden die einzelnen Spalten durchlaufen
		for (var h=0; h<12; h++) 
		{
			// substr() gibt den Teil von string zurück, der durch die Parameter start und length definiert wurde
			// $rest = substr("abcdef", 0, 4); // gibt "abcd" zurück
			// $rest = substr("abcdef", 1, 3); // gibt "bcd" zurück

			// row beinhaltet im ersten Durchlauf die erste Zeile der ersten Spalte -> Position: 0/0 
			// 0*2 =  0  -> von 0  bis 1
			// 1*2 =  2  -> von 2  bis 1 ?
			// ...
			// 11*2 = 22 -> von 22 bis 1 ?
			
			// h*2 == startpunkt  /  1 == Endpunkt
			var v = row.substr(h * 2, 1);
			
			// Falls die spalte nicht leer sein sollte -> d.h. wenn hier ein Block vorhanden ist
			if (v != "0") 
			{
				// brick ist ein Array -> running ist der Arrayindex == 0
				// Array beinhaltet an der Stelle 0 die brick MC aus der Bib. mit dem Instanznamen brick0 auf Ebene 0 
				//                                1                                                brick1           1 usw...
				
				//                                 Bibname     Instanzname      Ebene
				brick[running] = field.attachMovie("brick", "brick" + running, running);
				// Ich hätte das Array 'brick-array' genannt.
				
				// Die parseInt-Methode gibt eine ganze Zahl zurück, die gleich der in numString enthaltenen Zahl ist. 
				// Falls kein Präfix von numString erfolgreich in eine ganze Zahl umgewandelt werden kann, 
				// wird NaN (Not a Number) zurückgegeben.
				
				// parseInt("abc")     // Returns NaN.	
				// parseInt("12abc")   // Returns 12.
				brick[running].bmode = parseInt(v, 10);
				
				// Die Einzelnen Blöcke werden positioniert.
				// Schleifendurchlauf 1 -> Block0 in Zeile0 und Spalte0
				brick[running]._x = h * 45; // 45 == Block Breite / h*45 -> immer um eine Breite weiter plazieren
				brick[running]._y = i * 20; // 20 == Block Höhe / i == Spalte
				
				// Array Index wird erhöht
				running ++;
			}
		}
	}
	go();
}

Zwei Passagen habe ich noch nicht verstanden:


// row beinhaltet im ersten Durchlauf die erste Zeile der ersten Spalte -> Position: 0/0
// 0*2 = 0 -> von 0 bis 1
// 1*2 = 2 -> von 2 bis 1 ?
// ...
// 11*2 = 22 -> von 22 bis 1 ?
// h*2 == startpunkt / 1 == Endpunkt
var v = row.substr(h * 2, 1);

und

// parseInt("abc") // Returns NaN.
// parseInt("12abc") // Returns 12.
brick[running].bmode = parseInt(v, 10);

Hier verstehe ich dein Vorhaben nicht.

Ich drücke dir weiterhin die Daumen .. :)

Gruß
Aaron
 
Zuletzt bearbeitet:
Hi,

also, ich lese die XML-Datei zeilen- bzw tagweise ein.

in
Code:
obj.childNodes[i].attributes.bricks;
bekomme ich den String für die Zeile, z.B. 1,0,1,1,2,2,2,2,1,1,0,1

Dann durchlaufe ich diesen String in einer weiteren Schleife und zwar immer zwei Zeichen auf einmal, so dass ich die Kommata überspringe. Dann bekomme ich die Farbe (bzw. den Status) für den jeweiligen Stein. 0 = Kein Stein! ;)
In "bmode" speichere ich diese Zahl. parseInt wandelt lediglich den String in einen Integerwert um (10 ist die Basis).

Die Objektkollision habe ich nun auch noch verbessert, Deine Idee hat mich nämlich angesteckt und ich bastele auch grade eine kleine Version des Spiels. So filtere ich z.B. zu steile Winkel hinaus, und schaue, ob ein getroffener Stein links und rechts Nachbarn hat; in dem Fall gibts nämlich kein Abprallen nach den Seiten, sondern nur nach unten oder oben.

Probleme gibts noch dann, wenn die Geschwindigkeit so hoch ist, dass ich mit der nächsten Bewegung einen Stein komplett überspringen würde - den ganzen Pfad zu durchlaufen wäre mir nämlich zu performanceintensiv...

Nun ja, wenn ich die Routine fertig habe, poste ich sie hier - vielleicht kannst Du ja damit etwas anfangen.

Gruß
.
 
Zuletzt bearbeitet:
Zurück