Websitenkommunikation zwischen zwei Usern

Hallo,

ich hab ein etwas schwierigeres Problem betreffend der Kommunikation auf einer Website zwischen zwei darauf befindlichen Usern. Um das Problem anschaulich darstellen zu können, muss ich wohl zuerst etwas ausholen.

Was die Internetseite selbst machen soll:
Auf ihr soll ein Spiel entstehen „Schiffe versenken“. Zwei Spieler sollen gegeneinander antreten können.

Weiterer Hintergrund zur angewendeten Programmiertechnik:
Die Internetseite ist mit HTML/PHP und das Spielfeld mittels Javascript/Ajax programmiert. Momentan ist sie so konzipiert, dass wenn Spieler 1 schiesst zuerst die Koordinaten in die Datenbank eingetragen werden, dies geschieht mittels Request (Ajax). Bei Spieler 2 hab ich nun zwei Möglichkeiten ausprobiert.
1.) Im Intervall wird ein Request ausgeführt, der auf neue Schüsse prüft und diese dann in das Spielfeld einträgt.
2.) Per Mouseover über ein Aktualisiernfeld bzw. hinter dem Spielfeld befindlichen DIV wird dieser Request ausgeführt.
Die beiden Requests kommen sich aber anscheind etwas in die Quere und werden nicht immer korrekt ausgeführt. Ein Umstellung auf Synchron verursacht noch mehrere Fehler und Unstimmigkeiten.
Mein neuer Ansatz wäre nun, soweit überhaupt machbar:
Wenn Spieler 1 schiesst, soll ein Befehl an den Browser von Spieler 2 übergeben werden, der dann bei Spieler 2 den Request zur Schussplatzierung ausführt.
Gibt es überhaupt eine solche Möglichkeit? Oder muss ich dazu wieder eine Funktion ausführen die andere Requests behindern kann?
Ich hoffe ich habs einigermaßen verständlich gemacht, was ich beabsichtige … blick selber kaum noch durch in meinem Codechaos (den ich deshalb auch noch nicht angefügt habe). Bin über jede Hilfe dankbar. Wenn irgendwelchen Angaben fehlen, versuche ich die nachzureichen (Code, etc.).

Gruß
Marco

Hallo Marco,

zu meinem Bedauern kann ich Dir bei diesem Problem nicht helfen. Mit PHP und serverseitiger Programmierung sowie AJAX habe ich keine Erfahrungen.

Ich hoffe, Du findest in Kürze Hilfe und verbleibe mit freundlichem Gruß

Detlef

Ok. Kein Problem :smile:. Trotzdem danke!

Hi Marco,

Hallo,

ich hab ein etwas schwierigeres Problem betreffend der
Kommunikation auf einer Website zwischen zwei darauf
befindlichen Usern. Um das Problem anschaulich darstellen zu
können, muss ich wohl zuerst etwas ausholen.

Was die Internetseite selbst machen soll:
Auf ihr soll ein Spiel entstehen „Schiffe versenken“. Zwei
Spieler sollen gegeneinander antreten können.

Weiterer Hintergrund zur angewendeten Programmiertechnik:
Die Internetseite ist mit HTML/PHP und das Spielfeld mittels
Javascript/Ajax programmiert. Momentan ist sie so konzipiert,
dass wenn Spieler 1 schiesst zuerst die Koordinaten in die
Datenbank eingetragen werden, dies geschieht mittels Request
(Ajax). Bei Spieler 2 hab ich nun zwei Möglichkeiten
ausprobiert.

1.) Im Intervall wird ein Request ausgeführt, der auf neue
Schüsse prüft und diese dann in das Spielfeld einträgt.

Grundsätzlich richtig. Dieser Ansatz wird als polling bezeichnet.

Beispielsweise könnte dies so aussehen:

function updateBoard ( coords )
{
// Update des Spielfeldes mit den neuen Koordinaten (coords)
}

var interval_identifier = setInterval (
function ()
{
// Asynchroner Request (pseudoCode!)
asyncRequest ( http://backend-url/, function ( coords )
{
if ( coords ) {
updateBoard ( coords );
}
} );
},
500
);

Ein Interval von 500 = 1/2s könnte den Webserver extrem belasten bei vielen Spielern. Solltest du hier eine hohe Aktivität erwarten müsstest du zumindest ein längere Dauer (>= 1s) einstellen oder im Extremfall das Konzept überdenken oder erweitern (z.B. nur updaten wenn der Spieler sich mit der Maus über dem Spielbrett befindet o.ä.).

2.) Per Mouseover über ein Aktualisiernfeld bzw. hinter dem
Spielfeld befindlichen DIV wird dieser Request ausgeführt.
Die beiden Requests kommen sich aber anscheind etwas in die
Quere und werden nicht immer korrekt ausgeführt. Ein
Umstellung auf Synchron verursacht noch mehrere Fehler und
Unstimmigkeiten.

Das sich Requests in die Quere kommen ist ausgeschlossen. Meist ist das auf ein Timing-/Kontext-Problem oder eine falsche Nutzung von Closures zurückzuführen. Ein Kontext-Problem tritt auf wenn z.B. der Javascript-Code (also beispielsweise definierte Funktionen) nicht global Verfügbar sind sondern nur während eines Events. Da kann es leicht passieren das Funktionen aufgerufen werden die in dem Kontext nicht sichtbar sind. Mein Rat wäre es, sich unbedingt Firebug zu installieren. Mit dessen Hilfe kannst du nachverfolgen wie die Requests aussehen und den Fehler eingrenzen. Meist kommt man da sehr schnell auf ein Fehler im Javascript-Code.
Desweiteren würde ich den Einsatz von Javascript-Bibliotheken (z.B. jQuery) empfehlen.

Mein neuer Ansatz wäre nun, soweit überhaupt machbar:
Wenn Spieler 1 schiesst, soll ein Befehl an den Browser von
Spieler 2 übergeben werden, der dann bei Spieler 2 den Request
zur Schussplatzierung ausführt.
Gibt es überhaupt eine solche Möglichkeit? Oder muss ich dazu
wieder eine Funktion ausführen die andere Requests behindern
kann?

Das ist so nicht möglich. Einfach gesprochen ist HTTP (Also WWW) eine Einbahnstraße. Es können nur Requests vom Browser an den Server gesendet werden. Umgekehrt nicht! Zumindest nicht ohne weiteres und meist führen alle Ansätze dies doch zu ermöglichen zu erheblichen Nachteilen, die es einfach nicht praktikabel machen. Der Grund dafür ist nicht HTTP selbst sondern unsere Internet-Infrastruktur (Stichwort: NAT / Routing).
Der einzige sinnvolle Ansatz ist wie oben schon beschrieben ‚polling‘, also das wiederholte Abfragen des Servers (Backend) ob neue Informationen verfügbar sind. Dieser Ansatz ist aber mächtig genug um alles Abzubilden was gewöhnlich benötigt wird. Hinweis: Der Server kann im Prinzip alles an der Browser senden, auch Funktionen in Form von JavaScript-Code was deinem Gedanken mit den Befehlen entsprechen würde.

Ich hoffe ich habs einigermaßen verständlich gemacht, was ich
beabsichtige … blick selber kaum noch durch in meinem
Codechaos (den ich deshalb auch noch nicht angefügt habe). Bin
über jede Hilfe dankbar. Wenn irgendwelchen Angaben fehlen,
versuche ich die nachzureichen (Code, etc.).

Gruß
Marco

Ich hoffe ich konnte dir ein wenig behilflich sein. Um dir hierbei noch weiter helfen zu können müsste ich dann dein Code sehen - aber bitte strukturiert :smile:

Grüße Chris

Danke für die ausführliche Antwort. Ein bisschen hat mir das schon geholfen. Ich ab jetzt dennoch mal meinen Code mit angehängt.

Dies ist der Code in der Hauptdatei die in die Seite direkt eingebunden wird (der javascript-Part):

window.setInterval(„SetShoots()“,1000);

Dies ist der Code für den ersten Request/Funktion der php-Datei:

<?php include("_settings.php");
include("\_connect.php"); include("\_functions.php"); header('Content-Type: text/xml; charset=utf-8'); // sorgt für die korrekte Kodierung header('Cache-Control: must-revalidate, pre-check=0, no-store, no-cache, max-age=0, post-check=0'); // ist mal wieder wichtig wegen IE $result = mysql\_query("SELECT \* FROM shoots WHERE game\_ID = '$gameID' AND user\_ID = '$user2\_ID' ORDER BY shoot\_ID DESC LIMIT 0,1"); while($data=mysql\_fetch\_array($result)){ $field = $data['field']; $hit = $data['hit']; switch($hit) { case "1": $content = 'url(gfx/bg\_1\_X.jpg)'; $event = '"Du wurdest getroffen! Dein Gegner darf nochmal!"'; break; case "0": $content = 'url(gfx/bg\_1\_O.jpg)'; $event = '"Glueck gehabt! Daneben! Du bist dran!"'; break; default: break; } } echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";

echo „\n“;
echo " „.„M_“.$field.“\n";
echo " „.$content.“\n";
echo " „.$event.“\n";
echo „\n“;
?>

Und dies der Code der vom zweiten Request.

<?php include("_settings.php");
include("\_connect.php"); include("\_functions.php"); header('Content-Type: text/xml; charset=utf-8'); // sorgt für die korrekte Kodierung header('Cache-Control: must-revalidate, pre-check=0, no-store, no-cache, max-age=0, post-check=0'); // ist mal wieder wichtig wegen IE $id = $\_POST['id']; $type = $\_POST['type']; $anz = "0"; $hit = "0"; $event = "Du hast leider nicht getroffen!"; $content = ""; $result = mysql\_query("SELECT \* FROM games WHERE games\_ID = '$gameID'"); while($data=mysql\_fetch\_array($result)){ $turn = $data['turn']; $user1 = $data['user1\_ID']; $user2 = $data['user2\_ID']; if(($turn == "0" AND $data['user1\_ID']==$userID) OR ($turn == "1" AND $data['user2\_ID']==$userID)){ $turn = "0"; }else{ $turn = "1"; } } if($turn == "1"){ $event = "Warte auf den Zug deines Gegners!"; $id = "event"; $content = 'url()'; }else{ if($userID == $user1){ $newturn = "1"; }else{ $newturn = "0"; } $result = mysql\_query("SELECT \* FROM ships WHERE user\_ID = '$user2\_ID' AND (pos1 = '$id' OR pos2 = '$id' OR pos3 = '$id' OR pos4 = '$id' OR pos5 = '$id')"); while($data=mysql\_fetch\_array($result)){ $hits = $data['hits']+1; $shipID = $data['ships\_ID']; mysql\_query("UPDATE ships SET hits = '$hits' WHERE ships\_ID = '$shipID' "); $family=$data['family']; if($family==$hits){ $event = "Du hast das gegnerische Schiff versenkt!"; }else{ $event = "Du hast einen Treffer gelandet!"; } $hit = "1"; $anz = "1"; if($userID == $user1){ $newturn = "0"; }else{ $newturn = "1"; } } if($anz=="1"){ if($type=="1"){ $content = 'url(gfx/bg\_1\_X.jpg)'; }else{ $content = 'url(gfx/bg\_2\_X.jpg)'; } }else{ if($type=="1"){ $content = 'url(gfx/bg\_1\_O.jpg)'; }else{ $content = 'url(gfx/bg\_2\_O.jpg)'; } } mysql\_query("UPDATE games SET turn = '$newturn' WHERE games\_ID = '$gameID'"); mysql\_query("INSERT INTO shoots ( shoot\_ID, game\_ID, user\_ID, field, hit) values ( NULL, '$gameID', '$userID', '$id', '$hit')"); } echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";

echo „\n“;
echo " „.$id.“\n";
echo " „.$content.“\n";
echo " „.$event.“\n";
echo „\n“;

?>

Fehler dürften sich aber ansich eher im JS Teil eingeschlichen haben … wobei ich nur zufällige Fehler bei der Ausgabe habe keine systematischen.
Fehler sind dabei z.B., dass er manchmal beim Schießen keinen Text ausgibt und das Bild nicht verändert. Der Datenbankeintrag erfolgt aber meist trotzdem und beim Gegner werden die Schüsse auch eingezeichnet.

Danke schonmal :smile:.

Gruß
Marco

Hi Marco,

zunächst eine Verständnisfrage. War es bei Schiffeversenken nicht so gewesen das nur ein Spieler jeweils ‚Schießen‘ kann und der andere derweil warten muss? Dein Code lässt mich nämlich vermuten das es in deinem Fall so ist dass beide Spieler beliebig oft hintereinander Schießen können (sozusagen einfach aufeinander los gehen können) - es gibt also keine Abfolge (was im übrigen denke ich zu dem Problem führt das du schilderst, nämlich das sich die Requests in die quere kommen).

Deinem Code nach zu Urteilen liegt das Problem an dem globalen Request-Objekt:

var request = false;

Alle drei Funktionen nutzen nämlich die gleiche Variable um ihr Request-Objekt zu speichern. Die Funktionen ‚SetShoots‘ und ‚Schuss‘ überschreiben diese bei jedem Aufruf, was gleichzeitig Bedeutet dass sie sich das Objekt gegenseitig überschreiben könnten. Das ist nicht ganz offensichtlich in Javascript aber an dieser Stelle möglich.
Grundsätzlich hast du nicht die optimale Architektur gewählt um die Anwendung zu schreiben - aber aller Anfang ist schwer :smile:
Wenn wir mal die Architektur außen vor lassen würde ich dir folgende Änderungen vorschlagen um das von dir beschriebene Problem (der sich in die quere kommenden Requests) zu lösen.

  1. Mach das Request-Objekt lokal und entferne die globale Request-Variable:

function SetShoots()
{
var request = false;
// sonstiger Code wie gehabt

}

und

function Schuss(id, type) {
{
var request = false;
// sonstiger Code wie gehabt

}

  1. Nutze eine Callback-Methode für den Aufruf deine ‚interpretRequest‘ und übergebe Ihr das Request-Objekt als Parameter:

Also statt „request.onreadystatechange = interpretRequest;“
wie folgt umformulieren (für beide Funtionen - ‚SetShoots‘, ‚Schuss‘):

„request.onreadystatechange = function () { interpretRequest (request) };“ // Request-Objekt sollte lokal sein (siehe 1.)

  1. Umschreiben der ‚interpretRequest‘-Funktion so das diese das Request-Objekt als Parameter erwartet.

also statt „interpretRequest()“

function interpretRequest(request)
{
// dein Code wie gehabt
// das Request-Objekt ist nun lokal du arbeitest also immer auf exakt ein Kopie.
}

  1. Ende - Hoffentlich läufts so :smile:

Wie gesagt - es ist keine besonders schöne Architektur aber ich vermute das Javascript noch Neuland für dich ist, weshalb alles andere vermutlich zu tief in die Materie gehen würde. Wie bereits gesagt, macht dir insbesondere die jQuery-Bibliothek das Leben sehr viel leichter. Asynchrone Requests werden mit Hilfe von jQuery ein wenig intuitiver bzw. leichter. Ich Programmiere schon eine ganze Weile unter anderem Javascript und habe großes Gefallen an dieser Sprache gefunden. Im austausch mit anderen Programmieren stelle ich immer wieder fest das diese Sprache unterschätzt wird… ich will hier aber nichts Predigen :smile: dennoch kann ich dir nur nochmal empfehlen dir Firebug für den Firefox mal näher anzuschauen, insbesondere wenn du ernsthaft Javascript programmieren willst (was in deinem Anwendungsfall der Fall ist).

Wenn das Problem immer noch nicht gelöst ist. Schick mir bitte gleich den geänderten Code mit. Dein PHP-Code und die Codierung sehen gut aus. Ich denke wir können uns wie du sagst auf den Javascript-Code beschränken.

Zur Sicherheit nochmal den gesamte Code falls meine Ausführungen nicht ganz klar waren :smile:

window.setInterval ( „SetShoots()“, 1000 );

// Schüsse einsetzen
// var request = false; // Lokale Variable verwenden!!!

// Request senden
function SetShoots()
{
var request = false;
// Request erzeugen
if (window.XMLHttpRequest) {
request = new XMLHttpRequest(); // Mozilla, Safari, Opera
} else if (window.ActiveXObject) {
try {
request = new ActiveXObject(‚Msxml2.XMLHTTP‘); // IE 5
} catch (e) {
try {
request = new ActiveXObject(‚Microsoft.XMLHTTP‘); // IE 6
} catch (e) {}
}
}

// überprüfen, ob Request erzeugt wurde
if (!request) {
alert(„Kann keine XMLHTTP-Instanz erzeugen“);
return false;
} else {
var url = „setshoots.php“;
// Request öffnen
request.open(‚post‘, url, true);
// Requestheader senden
request.setRequestHeader(‚Content-Type‘, ‚application/x-www-form-urlencoded‘);
// Request senden
request.send();
// Request auswerten
request.onreadystatechange = function () { interpretRequest ( request ) };
}
}

// Schuss abgeben
// Request senden
function Schuss(id, type)
{
var request = false;
// Request erzeugen
if (window.XMLHttpRequest) {
request = new XMLHttpRequest(); // Mozilla, Safari, Opera
} else if (window.ActiveXObject) {
try {
request = new ActiveXObject(‚Msxml2.XMLHTTP‘); // IE 5
} catch (e) {
try {
request = new ActiveXObject(‚Microsoft.XMLHTTP‘); // IE 6
} catch (e) {}
}
}

// überprüfen, ob Request erzeugt wurde
if (!request) {
alert(„Kann keine XMLHTTP-Instanz erzeugen“);
return false;
} else {
var url = „schuss.php“;
// Request öffnen
request.open(‚post‘, url, true);
// Requestheader senden
request.setRequestHeader(‚Content-Type‘, ‚application/x-www-form-urlencoded‘);
// Request senden
request.send(‚id=‘+id+’&type=’+type);
// Request auswerten
request.onreadystatechange = function () { interpretRequest ( request ) };
}
}

// Request auswerten
function interpretRequest(request)
{
switch (request.readyState) {
// wenn der readyState 4 und der request.status 200 ist, dann ist alles korrekt gelaufen
case 4:
if (request.status != 200) {
alert(„Der Request wurde abgeschlossen, ist aber nicht OK\nFehler:“+request.status);
} else {
// Antwort des Servers -> als XML-Dokument
var xmlDoc = request.responseXML;
// Namen aus dem XML-Dokument herauslesen
var id = xmlDoc.getElementsByTagName(‚id‘)[0].firstChild.nodeValue;
var content = xmlDoc.getElementsByTagName(‚content‘)[0].firstChild.nodeValue;
var event = xmlDoc.getElementsByTagName(‚event‘)[0].firstChild.nodeValue;
// Namen in die Felder schreiben
document.getElementById(id).style.backgroundImage = content;
document.getElementById(‚event‘).innerHTML = event;
}
break;
default:
break;
}
}

Hallo, Marco,

Bleib bei asynchron. Wenn ich das schreiben wuerde wuerde ich regelmaessig (1/2 x pro Sekunde) per Ajax nach dem letzten Zug fragen - wenn der aktuelle Spieler nicht am Zug ist, unabhaengig von Mausaktionen. Wenn der aktuelle Spieler nicht am Zug ist, sollte er natuerlich auch keine Zuege ziehen duerfen. Ist er am Zug, muss nicht aktualisiert werden. Ich wuerde drei API-Calls definieren: Einen, der den gesamten Spielzustand herunter laedt (falls der Browser neu gestartet wird), einen der nur den letzten Zug laedt, und einen mit dem der Spieler seinen Zug macht. Optional noch einen um das Spiel abzubrechen, falls man keinen Bock mehr hat.

Hilft dir das?

Ciao!
Kai

Hallo Chris,

super!! Das funktioniert jetzt wunderbar!! Vielen vielen Dank!!
Zu deiner Verständnisfrage:
Ja, das ist auch bei uns so und wird über den Datenbaneintrag „turn“ gesteuert. Das funktioniert auch soweit ganz gut. Es wird dadurch auch sichergestellt, dass man nach einem Treffer nochmal schießen darf. Die Abfrage ob man schießen darf oder nicht erfolgt im „Schuss-Request“ selbst.

Bei einer anderen Funktion ist jetzt allerdings auch noch ein Fehler aufgetreten, wär super wenn du dir das auch noch kurz anschauen könntest.
Diese Funktion wird OnLoad gestartet und dient dazu, dass beim Reloaden oder Neustarten vom Browser die alten Eintragungen (Schüsse) komplett wieder da sind.
Dazu hab ich folgende Funktion gebaut (die Schleife ist wohl nicht optimal, aber funktioniert):

// Speichern/Reload
function reloadShoots(){
var i = „0“;
while(i \n";
echo „\n“;
echo " „.„M_“.$id.“\n";
echo " „.$content.“\n";
echo „\n“;
}
?>

Hab das ganze mit Firebug überprüft. Er bringt mir keine Fehlermeldungen. Er durchläuft auch die Schleife 100mal und gibt jedesmal das echo aus. Was er nicht macht, das Hintergrundbild dementsprechend verändern.
Was ich auch überprüft hab, ist im „interpretRequest“ zum schluss noch ein alert() hinzuhängen. Das hat er nicht ausgeben, erst als der interpretRequest über den SetShootsrequest gelaufen ist.

Hier nochmal der InterpretRequest:
// Request auswerten
function interpretRequest(request) {
switch (request.readyState) {
// wenn der readyState 4 und der request.status 200 ist, dann ist alles korrekt gelaufen
case 4:
if (request.status != 200) {
alert(„Der Request wurde abgeschlossen, ist aber nicht OK\nFehler:“+request.status);
} else {
// Antwort des Servers -> als XML-Dokument
var xmlDoc = request.responseXML;
// Namen aus dem XML-Dokument herauslesen
var id = xmlDoc.getElementsByTagName(‚id‘)[0].firstChild.nodeValue;
var content = xmlDoc.getElementsByTagName(‚content‘)[0].firstChild.nodeValue;
var event = xmlDoc.getElementsByTagName(‚event‘)[0].firstChild.nodeValue;
var div = xmlDoc.getElementsByTagName(‚div‘)[0].firstChild.nodeValue;
// Namen in die Felder schreiben
document.getElementById(id).style.backgroundImage = content;
document.getElementById(div).innerHTML = event;
}
break;
default:
break;
}
}

Ich kann mir das atm nicht erklären, warum er nichts verändert obwohl aber anscheinend eine Ausgabe stattfindet.

GRuß
Marco

Hallo Kai,

vielen Dank für deine Antwort! Hab mittlerweile die Fehler gefunden, es lag an globalen Variablen die eigentlich lokal hätten sein müssen.
Deinen Rat hab ich beherzigt, auch das mit den Spielständen laden … das klappt leider nicht so ganz wie ich mir das vorgestellt hatte. Kann aber momentan keinen Grund finden.

Viele Grüße
Marco

Hi Marco,

bevor ich tiefer in dein Code einsteigen will ich mal ein Schuß ins Balue wagen. Nachdem du sagst das der Request an sich gut ausschaut vermute ich stark das in dem Augenblick wo du dein Spielfeld initialisieren wills (also die Hintergrundbilder setzen wills) das DOM noch nicht geladen ist, was soviel bedeutet das die DIV’s noch nicht geladen sind.

Wie genau sieht dein Einsprung aus? Benutz du das onLoad-Event auf dem Body-Tag oder auf dem Window-Objekt?
Vielleicht reicht es aus wenn du, statt onLoad zu verwenden, dein Script am Ende des Dokumetes ausführst also in etwa so:




reloadShoots ();

Ist dein Projekt denn eigentlich schon Online verfügbar. Wenn du mir die URL sendest kann ich mir das Problem vielleicht auch schon direkt online anschauen.

Das mit dem Alert habe ich noch nicht verstanden. Wenn ich dich richtig verstanden habe hast du testweise ein alert am Ende der interpretRequest-Funktion eingefügt. Das würde aber bedeuten das dieses alert 100 mal ausgegeben werden müsste!?
Weiter ist mir aufgefallen das du die Varible i als string initialisierst: var i = ‚0‘; Auch wenn es funktioniert ist das nicht ganz richtig und kann in unterschiedlichen Browsern zu Fehlern führen.
Richtig wäre var i = 0;
Entsprechend müsste deine Abfrage ob diese kleiner 100 ist so aussehen while ( i

Ich hatte es tatsächlich als onload. Hat jetzt aber auch so leider nicht funktioniert.
Dass ich die noch gar nicht mitgegeben habe …
die Url ist: http://seeschlacht.co.de … von KILU.de ein kostenloser Server.

Wenn´s funktioniert hätte, hätte er das tatsächlich 100 mal ausgeben müssen, was er allerdings nicht hat.
Hatte ich zuerst auch so … ka, warum ich´s geändert hab.

Danke schonmal für deine Mühe … aber Stress dich net zu sehr rein, dass muss wirklich net sein. Ich bin jetzt dann eh für 2 Tage ausgeflogen. Und kann zwar Emails etc. lesen aber an der Site nicht weiterbauen.

Ich seh auch gerade noch im Code, die Variable Loop. Das ist ein ÜBerbleibsel einer anderen MEthode die ich ausprobiert hatte für die Schleife, damit ich se net 100 mal durchlaufen lassen muss, sondern aufhört wenn keine Schüsse mehr da sind. Hat aber nicht funktioniert. Ich denke man dürfte der jetzt keine beachtung mehr schenken.
Nur für den Fall, dass du dich fragst für was da loop = true steht.

mir fällt gerade ein … Ohne login daten kommst du nicht weit.
benutzername : gast … Passwort: baum
Testspielfeld 2 auf home