Paul Schmitz schrieb:> Kann man daraus was sinnvolles bauen?
rein mit javascript nicht wirklich - man kann zwar das spielprinzip
nachbauen, als verteilte anwendung jedoch relativ witzlos, da man sich
mit einfachsten mitteln einfach selbst bereichern kann.
als ajax-anwendung (evtl. mit KI) könnte man da schon ein bisschen mehr
daraus machen, erfordert aber ein bisschen hirnschmalz um den datenstand
aller mitspieler synchron zu halten und auch manipulationen
auszuschließen
anonym schrieb:> rein mit javascript nicht wirklich - man kann zwar das spielprinzip> nachbauen, als verteilte anwendung jedoch relativ witzlos, da man sich> mit einfachsten mitteln einfach selbst bereichern kann.
Wenn man nicht gerade einen Knopf einfügt 'sich selbst Geld geben' und
Tastenkombinationen blockiert, ist das eigentlich ganz gut (keine
Konsole). Man spielt dann statt mit einem Brett virtuell.
Man könnte sogar von verschiedenen Rechnern aus spielen, wenn man auf
dem Server den Spielstatus in eine Datei schreibt und diese immer wieder
ausliest.
Daniel A. schrieb:> function Feld(){> var e = document.createElement("div");> this.getElement=function(){> return e;> };> }> var feld = new Feld();
Ich habe den Code mal getestet, die Erzeugungsfunktion tut jedoch in
Firefox und Chrome nichts. Eigentlich sollte doch ein div erzeugt
werden, oder?
Das wird es auch! Aber das div wurde zu keinem element im document tree
hinzugefügt. Dafür gibt es die methode:
1
parentNode.appendChild(newNode)
Dann kann man im document ein element mit der id spielfeldContainer
erstellen, erstellt eine instanz seiner Spielfeld klasse und ruft
getElement und appendChild auf um es dem dokument hinzuzufügen. Die
spielfeld klasse erstellt wiederum instanzen der Feld klassen,
registriert deren root element an der richtigen stelle, und baut so das
Spielfeld zusammen. Vorteil: Du musst den Elementen keine ID geben, und
kanst deren referenzen z.B. in einem Array speichern. Die instanzierun
der Felder und das setzen derer eigenschaften, etc. kann danach in einer
einfachen schleife gelöst werden, und eine Änderung für alle Felder wird
zu einer einzigen in der Feld klasse.
So, im Anhang befinden sich einige Funktionen:
Feld: addText fügt einen Text zum Feld hinzu, clear löscht diesen
msg: show zeigt einen Text, hide versteckt diesen
player: Geldverwaltung: addmoney fügt Geld hinzu, removemoney zieht
welches ab, ein Player hat normal 0€
Straße: name,miete,kaufpreis,houses sind gesetzt, changeplayer ändert
den Spieler, die Variable this.player ist normal undefined, buy(player)
kauft die Straße, buyhouse(player) kauft ein Haus und multipliziert die
Miete mit dem Wert (EDIT: hat noch einen kleinen Fehler), addFeld macht
diese Straße als Feld sichtbar
Definiert muss nur noch das folgende werden:
1
var strasse1 = new strasse ("Schlossstraße",50,400);
OK, der Ansatz ist gut, aber es gibt einige störende Details, z.B. die
Funktion buy in der classe Strasse, nicht die Strasse kauft den Player,
es ist umgekehrt! Du könntest die Funktion setOwner nennen, und die buy
funktion im player, diese ruft dort die setOwner funktion der Strasse
und seine eigene removemoney funktion auf, welche optional private sein
könnte.
Ausserdem: Verwende NIEMALS eval, denn eval ist böse!
1
// Schlechte lösung
2
var geldabziehen=this.player+".removemoney ("+this.kaufpreis+");";
3
eval (geldabziehen);
4
5
// korrekte lösung 1
6
this.player.removemoney(this.kaufpreis);
7
8
// korrekte lösung 2
9
var geldabziehen=this.player.removemoney.bind(this.player,this.kaufpreis);
10
geldabziehen();
11
12
// korrekte lösung 3
13
var geldabziehen=this.player.removemoney.bind(this.player);
Okay.
Daniel A. schrieb:> Ausserdem: Verwende NIEMALS eval, denn eval ist böse!
Wieso gibt es das dann? Und was ist äquivalent zu diesem, aber nicht
böse?
Mit deinem Code (anstatt von eval,
1
var geldabziehen=this.player.removemoney.bind(this.player);geldabziehen(this.kaufpreis);
) erhalte ich nur "TypeError: this.player.removemoney is undefined".
Der Player kann nun verschoben und angezeigt werden.
Paul Schmitz schrieb:> Wieso gibt es das dann? Und was ist äquivalent zu diesem, aber nicht> böse?
Eval kann alles, deshalb ist es böse. Es gibt kein gutartiges equivalent
zu eval, obwohl sandboxing mit workern schon sehr nah dran ist.
> Mit deinem Code (anstatt von eval, var> erhalte ich nur "TypeError: this.player.removemoney is undefined".
Ups, ich dachte this.player wäre eine referenz auf einen player, ist
aber ein string mit dem Namen der playervariable, das ist ein
Designfehler und sollte korrigiert werden.
Das "sicherere" equivalent zur Zeile:
1
var geldabziehen=this.player+".removemoney ("+this.kaufpreis+");";
2
eval (geldabziehen);
3
// besser, aber nicht gut, weil window globaler scope ist
4
window[this.player].removemoney (this.kaufpreis);
Die player sollten bei dieser zugriffsmethode aber in einem objekt oder
array gespeichert und window durch den identifier einer referenz auf das
objekt/array ersetzt werden.
Nun habe ich eine per Javascripteingabe funktionierende Version gebaut.
Befehle:
- player1.addmoney(1000)
- player1.removemoney(1000)
- player1.moveAbsolute(1)
- player1.moveRelative(2)
- player1.showPlayerDiv()
- strasse1.setOwner("player1")
- strasse1.changeplayer("player2")
- strasse1.buyhouse()
- msg.show("Nachricht")
- msg.hide()
- controls.wuerfle()
Mit der Control-Funktion werden später diese Funktionen aufgerufen.
EDIT: Habe in Wikipedia ein schönes Spielfeld gesehen, das mit
HTML-Tabellen erzeugt ist. Vielleicht kann man daraus ja noch was
machen. http://de.wikipedia.org/wiki/Monopoly#Das_Spielfeld
Nur um dass mit dem eval nochmal gesagt zu haben:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#Don.27t_use_eval.21
Dashier stört mich immernoch:
strasse1.setOwner("player1")
besser wäre:
strasse1.setOwner(player1)
und dann statt
window[this.player].removemoney (this.kaufpreis);
folgendes:
this.player.removemoney(this.kaufpreis);
Es macht einfach keinen sinn den namen einer globalen variablen zu
übergeben, nur um später einen lookup im globalen scope manuell
durchzuführen, um eine referenz dieser variable zu erhalten. Wenn du die
Variable direkt übergiebst, übergibst du nur dessen Referenz (ausser bei
primitiven datentypen).
Jetzt eine Neuerung:
Die Controls werden mit controls.run (playerN) aufgerufen. Nach einem
Zug wird der Spieler automatisch gesetzt und Miete (wenn nötig)
automatisch gezahlt. Die Spielerposition wird immer dargestellt.
Eine Funktion um Straßen zu belasten (umdrehen) ist noch nicht
eingeführt, da dies etwas komplexer ist:
- Der Spieler muss die Straße auswählen können
- Der Spieler bekommt einmalig das Geld für den Straßenwert aber keine
Miete mehr
- Der Spieler muss auswählen können, wann er das Geld wieder
zurückzahlen muss (mit 10% Zinsen)
Die Tabelle von Wikipedia wurde teilweise schon eingebaut (untere Felder
für die ganze Tabelle sehe ich aber noch keine Möglichkeit), um die alte
Version zu nutzen muss nur der Name von FeldCp() und Feld() vertauscht
werden und die Tabelle gelöscht werden.
Nun habe ich mal die Controlfunktion geupdated, der playerdiv
funktioniert aber nicht mehr :(
Nach Reparatur kommt dann:
- Gemeinschaftsfeld und ?-Feld
- Gefängnis
Nun gibt es einige Knöpfe.
Nach Eingabe von controls.run(player1) oder controls.run(player2) und
drücken von 'Kaufen' erscheint ein Knopf mit der action
'strasse2.setOwner ([object Object]);'. erzeugt wird das mit
blablabla.innerHTML+="<button
onclick='strasse"+this.player.position+".setOwner
("+this.player+");'>Kaufen</button><br>";. Was ist da falsch (ich meine
das natürlich im Erzeugungscode, nicht die Tatsache, dass da [object
Object] steht)?
Paul S. schrieb:> blablabla.innerHTML+="<button> onclick='strasse"+this.player.position+".setOwner> ("+this.player+");'>Kaufen</button><br>";. Was ist da falsch (ich meine> das natürlich im Erzeugungscode, nicht die Tatsache, dass da [object> Object] steht)?
innerHTML würde ich immer vermeiden (ausser wenn ich den inhalt von divs
Löschen muss.
Hinweis: this.player+"" ist equivallent zu this.layer.toString() was zu
"[Object object]" evaluiert.
Ungetestet:
Hierbei ist anzumerken, dass man this.player.position durch eine
Referenz auf die Strasse ersezen könnte. Dadurch würde die verwendung
von window[...] überflüssig. Oder die Strassen in ein Array packen, dann
wird aus window['strasse'+this.player.position] folgendes:
strassen[this.player.position]
Am besten beides kombinieren.
Die Funktion Zug sieht funktioniert so nicht (ungetesteter Code ist
drin, gekennzeichnet durch Kommentare). Der Knopf erscheint, beim
klicken auf diesen passiert jedoch nichts (und nichts ist zu wenig).
1
this.zug=function(player){
2
this.player=player;
3
var w=this.wuerfle();
4
document.getElementById("msg").innerHTML+=this.player.name+" ist dran<br>Die Würfel sind addiert "+w+".<br/>Der Spieler wurde gesetzt.<br>";
document.getElementById("msg").innerHTML+="Die Straße ist schon an "+window["strasse"+plpos].player.name+" verkauft, die Miete beträgt "+window["strasse"+plpos].miete+". Die Miete wurde gezahlt.<br>";