Bismuth

Kommentare anzeigen Worklog abonnieren

Worklogs Bismuth

Bootstrapping und mehr

Samstag, 23. Juni 2012 von Noobody
Wir leben noch!

Über die letzten Wochen arbeitete ich, wie in den letzten Posts erwähnt, daran, den Compiler in Bismuth selbst neu zu schreiben.
Die Arbeit daran kommt bisher gut voran. Lexer, Parser und AST sind aufgesetzt und laufen schon ziemlich gut - als Test liess ich den Parser sich seber parsen, was tatsächlich funktionierte (obwohl mir jetzt der Kopf schwirrt... zu viel Rekursion).

Da der Parser nun in Bismuth selber geschrieben ist, besteht im neuen Compiler keine Abhängigkeit mehr auf Bison (den Parsergenerator, den wir bisher verwendet haben). Obwohl Bison eine flotte Sache ist, war das C-zu-BMax Interface ein wenig unschön (da man prozeduralen C-Code mit OOP-Code mixen musste). Trotzdem aber bin ich froh, dass der erste Parser noch über Bison lief, da man so sofort Mehrdeutigkeiten in der Grammatik feststellen konnte und man durch die Grammatikregeln schon einen ziemlich genauen Plan erhält, wie der entsprechende Parser aufgebaut werden muss.

Als nächsten Schritt kommt nun die semantische Analyse und die Codegenerierung, einfach nun neu geschrieben in Bismuth selbst. Sobald das steht, ist der Compiler in der Lage, sich selber zu kompilieren - keine Abhängigkeit mehr auf BMax! Bis dahin geht es natürlich noch eine Weile, aber wir sind auf gutem Wege.

Da ich nun gezwungen bin, in Bismuth zu programmieren und den Bismuth Debugger zu verwenden, ist es nun um einiges leichter, Designfehler und bugs zu finden. Im Compiler selbst fand ich bisher erstaunlicherweise nur zwei Bugs, aber die IDE erhielt einige neue Features wie z.B. automatische Einrückung, ergänzen von End Method/Function/Class etc. während des Tippens und automatische Konstruktorgenerierung auf Knopfdruck. Ein paar Module mussten gefixt werden, aber wirklich gravierendes habe ich bisher nicht gefunden.

Der momentane Code des Compilers in BMax is zugegebenermassen ziemlich unschön, was ich daran merke, dass ich ab und zu Mühe habe, durch alten Code noch durchzublicken - kein gutes Zeichen! Daher gebe ich mir Mühe, beim Rewrite in Bismuth schönen Code zu produzieren und den gemachten Fehlern zu lernen.
Eines der gezogenen Konsequenzen ist es, den AST nun mittels visitor pattern zu bearbeiten. Damit hält man die Daten und die Algorithmen, die darauf arbeiten, voneinander getrennt. Das macht bei kleineren Datenstrukturen keinen Sinn, aber beim AST, der viele verschiedene Operationen (annotation, analyse, transformation, codegenerierung etc.) unterstützen muss, ist es durchaus sinnvoll, die Algorithmen in einzelne Phasen und Klassen zu unterteilen und die eigentliche Datenstruktur kurz, sauber und übersichtlich zu halten.
Ein anderer Vorteil ist auch, dass Coderedundanz vermindert wird - die Logik, um den Baum komplett zu durchwandern, ist nun in der Klasse WalkingVisitor implementiert. Will man nun bestimmte Knoten des Baumes abarbeiten, macht man eine neue Klasse mit dem WalkingVisitor als Superklasse, überschreibt die entsprechenden Methoden und muss sich um den Rest des Baumes gar nicht kümmern.

Will man zum Beispiel die Namen aller Methoden in einem Stück Code ausgeben, muss man nur noch folgendes machen: BlitzMax: [AUSKLAPPEN]
Class PrintingVisitor Extends WalkingVisitor
Method VisitMethod(Node:MethodNode)
Print(Node.Identifier)
Super.VisitMethod(Node)
End Method
End Class

Sehr viel einfacher, als die komplette Logik zum durchwandern des gesamten AST neu zu implementieren, bis man die Liste der Methoden bekommt Razz

Die neuste Version des Compilers (mit allen Bugfixes) bekommt ihr hier

IDE, Debugger und mehr

Montag, 4. Juni 2012 von Noobody
Nach Ringen und Würgen mit wxWidgets und gdb steht nun eine erste funktionierende Version eines Debuggers für Bismuth!
Es gibt natürlich noch viel zu verbessern, aber da er nun produktiv einsetzbar ist, folgt der nächste Punkt im Programm - portieren des Compilers nach Bismuth. Da ich dann gezwungen bin, meine eigenen Tools statt BMax zu verwenden, fallen mir hoffentlich die meisten Missstände im Debugger und im Bismuth-Compiler (und auch der Sprache selbst) auf, damit ich sie beheben kann. Nichts ist schlimmer als ein Entwickler, der sein Programm nie ernsthaft benutzt hat Razz

Erst mal ein kleiner Screenshot:
user posted image

Links ist die Liste aller momentan sichtbaren Variablen (ja, die Werte stimmen - ist mein Code fürs aktuelle BlitzQuiz). Unten links ist der Callstack, welche die aufgerufenen Funktionen zeigt und zwischen den einzelnen Funktionen wechseln kann. Im Moment ist die Liste noch ungefiltert (d.h. Bismuth-Interne Funktionen sind auch drauf), aber das wird noch behoben. Unten in der Mitte sind die verschiedenen Output-Tabs: in Output ist die Standardausgabe des Programms, in Console Konsolenoutput des Debuggers, in Info zusätzliche Laufzeit-Info (wird vermutlich irgendwann mit Console zusammengelegt und in Build der Output des Compilers (Warnungen etc.).

Die roten Punkte in der linken Leiste sind die aktiven Breakpoints. Das aus BMax bekannte DebugStop (Stop in B3D) gibt es nicht mehr - dafür kann man die Breakpoints einfach im Debugger selbst setzen/löschen. Geht sogar zur Laufzeit, was sehr praktisch ist, wenn man einen Breakpoint vergessen hat und nicht neu kompilieren will.

In der Mitte ist der Codeeditor, welcher dank Scintilla sehr schnell ist und sämtlichen Schnickschnack beherrscht. Wirklich eingebaut ist erst wenig, aber je nach Zeit und Bedarf folgen dann irgendwann Folding, Autocompletion, Codeanalyse etc. Meine geliebten Tastenkombos aus Eclipse und SciTE habe ich aber natürlich schon eingebaut
Im Moment ist noch der Style aus dem alten SciTE-Editor standardmässig aktiviert, aber da ich nun vom Code aus Zugriff auf Scintilla habe, ist es ein leichtes, verschiedene (und auch Benutzerdefinierte) Styles zu verwenden. Es haben sich ja schon ein paar Leute wegen des schwarzen Hintergrunds beschwert, was ich durchaus verstehen kann.


Wie am Anfang des Posts erwähnt, lief bei der Entwicklung natürlich nicht alles glatt (tut es doch nie Razz ). Hauptübeltäter waren dabei:

1. GDB

GDB (der C/++-Debugger von GCC) ist eigentlich eine super Sache. Er enthält ein standardisiertes, speziell für Frontends entwickeltes Protokoll namens gdb/mi, welches es erlaubt, per Pipes Befehle an gdb zu senden und Nachrichten von gdb auszulesen. Die Dokumentation ist okay, GDB selbst hält sich auch bis auf ein paar Ausnahmen daran, ein Parser und Interpreter dafür ist schnell geschrieben - klingt ja alles einfach! Wäre da nicht Windows.

Grösster Problem ist, dass ein normal gestarteter gdb (in der CMD gdb -i mi Test.exe) den Output des gedebuggten Programms (ausgegeben mit z.B. Print) mit dem Output des Debuggers (sprich, gdb/mi-Protokoll) vermischt. Eigentlich logisch, denn er bekommt nur eine Input/Output-Pipe und kann den Output des Programms nirgends anders hinschreiben.
Das Problem haben die Entwickler von gdb erkannt und den tty-Befehl eingeführt, der es einem erlaubt, den Input/Output des Programms auf ein anderes Terminal umzuleiten. Will man den Output nun in der IDE abfangen, kann diese nun einfach ein Pseudoterminal erstellen, per tty den Output umleiten und tadaa! hat getrennte Input/Output-Pipes für gdb und gedebuggtes Programm.

Klingt ja schön und gut - nur kennt Windows weder Terminals noch Pseudoterminals, sprich, tty funktioniert schlichtweg nicht. Ich habe sämtliche passenden Mailing-Listen durchstöbert und eine vollständig funktionierende Alternative gibt es nicht. Zwei Workarounds werden empfohlen:
1. Wenn man Input/Output von der IDE aus handhaben will, muss man wohl oder übel gdb normal aufrufen und versuchen, zwischen gdb/mi-Nachrichten und Output des Programms mit ein wenig String/Regex-Hexerei zu unterscheiden. IDEs wie Eclipse oder Code::Blocks machen das so (die verwendeten regexes sind nicht hübsch). Wenn das gedebuggte Programm etwas ohne Linefeed am Ende ausgibt (z.B. mit WriteStdOut) oder etwas, was aussieht wie eine gdb/mi-Nachricht (z.B. etwas mit =, + oder ~ am Zeilenanfang), dann kracht einem die IDE weg. Kacke!
2. Man benutzt den gdb-Befehl -set new-console on, was dazu führt, dass ein Konsolenfenster aufpoppt und der Input/Output des Programms dort erscheint. Zwar kann nun ohne Probleme die IDE mit gdb kommunizieren, weil der Output des Programms in einem komplett anderen Fenster erscheint, aber für den Benutzer ist das natürlich auch schlecht. Weil die Windows-Konsole so unangenehm ist (Fenster vergrössern, Text kopieren/einfügen etc.), wäre es extrem lästig, ein I/O-intensives Programm zu debuggen. Also auch keine gute Lösung!

Schlussendlich kam ich nach verzweifeltem Grübeln dann auf eine dritte Lösung. gdb ist in der Lage, sich an laufende Prozesse anzuhängen (z.B. um bei einem bereits gecrashten Programm herauszufinden, wo und warum der Crash passierte). Dabei behält das Programm aber seine Input/Output-Streams, weil gdb diese logischerweise zur Laufzeit nicht einfach so umhängen kann. Wenn also die IDE das zu debuggende Programm startet, den gdb dann anhängt, hat es effektiv zwei verschiedene Input/Output-Streams für Programm und Debugger!
Das letzte zu lösende Problem ist dann, dass das Programm in der Zeit zwischen Programmstart und anhängen des Debuggers schon irgendwo in der Ausführung ist (und vielleicht schon einen Breakpoint verpasst oder einen Crash verursacht hat). Ein schneller Griff in die Windows-API löst das aber glücklicherweise! Beim Starten des Programms einfach CREATE_SUSPENDED CreateProcess als Flag übergeben, dann die PID des gestarteteten, aber noch schlafenden Programmes auslesen, GDB an die PID anhängen, alle Breakpoints setzen und dann das Programm mit ResumeThread aufwecken.

Funktioniert hervorragend! Ist zwar weitaus komplizierter als ein einfaches tty, aber was macht man nicht alles für Windows-Support Razz

2. wxWidgets

Das Problem war weniger mit wxWidgets (gigantisches GUI Toolkit), sondern mit wxMax (wxWidgets als BMax-Modul gewrappt). Brucey, der ursprüngliche Autor des Moduls, ist seit zwei Jahren mehr oder weniger tot. Da die Qualität des Moduls ausgezeichnet ist, wäre das nun weniger schlimm, hätte sich nicht der Rest der Welt weiterentwickelt. wxMax wurde damals nämlich mit g++ 3.6.2 kompiliert, aber mittlerweile sind wir bei 4.6.2! Logischerweise führen die knapp fünf Jahre gcc-Entwicklung dazwischen dazu, dass kompilierte Binaries nicht mehr untereinander kompatibel sind. Wer also kein altes BMax mit altem ld, alten MinGW-Libraries und ein altes MinGW installiert hat, kann es also komplett vergessen, das Modul zu benutzen (zehntausende Linkerfehler).

Mangels Alternative habe ich mich ein paar Stunden an MaxGUI versucht, war aber von der API so entsetzt, dass ich mich lieber ein paar Tage daran setzte, wxMax wieder zum Laufen zu bringen.
Im Prinzip musste ich nur wxWidgets (die C++-Library, nicht das BMax-Modul) mit den richtigen Einstellungen (den gleichen, wie Brucey damals hatte) neu kompilieren, ld/ar im BMax-Ordner updaten, die richtigen Libraries in BMax/lib ersetzen und ein paar Module abändern, aber mancher Kaffeepot musste seinem Ende entgegenblicken, bis ich das durch Trial-and-Error herausfand. Ich habe einen kleinen Guide geschrieben, falls andere interessiert sind. Ist mit ein wenig Aufwand verbunden, aber das war mir ein funktionierendes wxWidgets wert Razz


Am Compiler tat sich in der Zwischenzeit (ausser ein paar Bugfixes) nicht viel.

Wenn man im Debugmodus (Flag -d) kompiliert, generiert der Compiler jetzt zusätzlich Dateien mit Debug-Informationen. Im Moment beinhaltet das nur ein Mapping von Bismuth-Zeilen nach C++-Zeilen und eine Liste der Scopes mit Zeilennummern und enthaltenen Variablen, aber das wird im Laufe der Zeit noch erweitert (eine Klassenliste wäre noch nötig).
Dafür musste ich im Prinzip das C++-Backend umschreiben, damit es den generierten Code nun nicht durch Stringoperationen zusammensetzt, sondern die einzelnen Elemente einer speziell dafür gedachten Klasse überreicht, die während der Generierung Debuginformationen sammelt. Ist aber sowieso besser so, denn die Stringoperationen waren nicht wirklich sauber.

Die aus C bekannten "character constants" sind jetzt eingebaut, die es einfacher machen, an ASCII-Werten von Zeichen zu kommen. Verwendet wird es mit einfachen Anführungsstrichen, z.B. 'a' (wäre das gleiche wie 97). Ist ein wenig handlicher als das in BMax nötige Asc("a") oder "a"[0].

Mir ist ausserdem aufgefallen, dass Literale nicht in der Dokumentation sind. Grundsätzlich funktionieren sie gleich wie in BMax, nur dass Strings sich über mehrere Zeilen erstrecken können (die Zeilenumbrüche gehören zum String dazu) und man den Typ von Zahlenliteralen nicht durch Anhängen von :Double, :Short etc. bestimmt, sondern durch anhängen von einzelnen Buchstaben.
[1.5:Double, 3.2:Double, 5.6:Double] in BMax entspräche also [1.5D, 3.2D, 5.6D] in Bismuth. Die erlaubten Kürzel sind L (Long), S (Short), B (Byte), D (Double) und jeweils UL, US, UB (gleich wie vorher, aber Unsigned). I und F werden nicht benötigt, da die entsprechenden Ganzzahl-/Dezimalliterale bereits standardmässig Int/Float sind.

Das BBP präsentiert: Bismuth!

Donnerstag, 17. Mai 2012 von Noobody
user posted image Bismuth

Anlässlich der genau 6 Monate Entwicklung an Bismuth ist es an der Zeit, endlich einen Worklog für das aktuelle Projekt von Chaos Interactive zu erstellen!

Was ist Bismuth?
Bismuth ist eine neue Programmiersprache, die sehr an BMax orientiert ist. Das Ziel ist, eine Sprache zu schaffen, die die Ungereimtheiten von BMax behebt und stattdessen Features implementiert, die schon seit einiger Weile von der Community verlangt werden. Der Compiler wird gratis und Open Source.

Wer steckt dahinter?
Der Grossteil von Chaos Interactive: (alphabetisch) BladeRunner, d-bug, hamZta, Noobody und Xeres.

Was ist der aktuelle Stand?
Sprache und Compiler sind im Moment auf einem ähnlichen Stand wie BMax jetzt. Zwar gibt es noch wenige Module, viele Baustellen und mit Sicherheit noch haufenweise Bugs, aber das Portieren von BMax-Sourcecodes geht jetzt meistens vergleichsweise schmerzlos.

Wie funktioniert es?
Der Compiler selbst ist in BMax geschrieben. Parser wird von Bison (einem Parsergenerator) bereitgestellt. Als Zwischenschritt wird C++ ausgegeben, welches dann mit g++ kompiliert und gelinkt wird. Als Garbage Collector wird BoehmGC verwendet.

Unterschiede zu BMax
....gibt es viele. Die wichtigsten sind aber:
- Programmcodes sind immer SuperStrict - alle Variablen müssen vor Benutzung deklariert werden
- Type heisst jetzt Class
- Funktionsaufrufe müssen zwingend mit Klammern geschehen (Print("Hello World") statt Print "Hello World")
- Kommentare werden mit // und /* */ eingeleitet statt ' und Rem End Rem
- Then bei If ist zwingend
Zusätzliche Features:
- Unsigned Datentypen
- Konstruktoren
- Public/Protected/Private für Klassen
- Multiline-Strings
- For-While-Do-Schleife (ähnlich wie for-Schleifen aus Sprachen wie C oder Java)
...und vieles mehr! Lest am besten einfach die Sprachspezifikation!

Was noch fehlt
Kurze Antwort: Vieles!
Lange Antwort: Typecasts, Private/Protected, Stringvergleiche, Module und noch einige andere können sich inkonsistent und verbuggt verhalten. Einige Elemente des Sprachdesigns sind meiner Meinung nach noch zu sehr an BMax orientiert und werden definitiv noch überarbeitet. Bison wird auch ersetzt durch einen eigenen Top-Down-Parser, um sich das hässliche C-Interface zu sparen und ordentliche Fehlermeldungen ausgeben zu können. Ein Debugger fehlt noch.

Was geplante Features angeht, sind auf jeden Fall Interfaces, Properties, Funktionsüberladung und Operatorenüberladung auf der Liste. Templates (a.k.a. Generics) sind eine Möglichkeit, haben im Moment aber noch keine Priorität.
Das, was man im Moment noch aus BMax vermisst (z.B. EachIn) muss noch warten, bis Interfaces implementiert sind. Zentrale Sprachelemente (wie z.B. Iteratoren) kann man dann selber durch das implementieren eines bereitgestellten Interfaces erweitern.

Download?
Natürlich!

Um den Compiler zum laufen zu bringen, braucht ihr folgendes:
1. Stellt sicher, dass ihr MinGW installiert habt (C++ Compiler für Windows). Um sicherzugehen, dass MinGW auf dem System vorhanden ist, öffnet die CMD und gebt g++ -v ein.
2. Ladet euch den Compiler hier herunter. Der Compiler ist vorkompiliert (bismuth.exe), aber wenn ihr BMax besitzt, könnt ihr ihn gerne neu bauen und dabei auch ein paar Blicke in den Source werfen.
3. Fügt den Ordner, in dem die bismuth.exe enthalten ist, zur PATH-Umgebungsvariable hinzu (googlet das am besten, wenn ihr nicht wisst, wie das geht). Um sicherzustellen, dass alles korrekt funktioniert, öffnet die CMD und gebt bismuth ein.
4. Kompiliert die Module neu. Öffnet dazu die CMD und gebt bismuth -m Bismuth.* ein und lasst ihn durchlaufen. Ist das gut gegangen, seid ihr schon fast fertig!
5. Ladet die rudimentäre IDE von hier herunter. Öffnet sie SciTE.exe, schreibt ein paar Programme, drückt F5 zum kompilieren und starten - tadaa! Bismuth läuft bei euch. Ihr könnt bei Gelegenheit mal Testcode\Noobody\Zaubercraft\Zaubercraft.bi öffnen (ein in Bismuth geschriebener Minecraft-Klon).

Ein paar Hinweise zur aktuellen Version:
- Es finden sich mit Sicherheit noch sehr viele Bugs. Ein paar der Dinge, die in der Sprachspezifikation beschrieben werden, sind noch nicht oder nur teilweise implementiert. Falls ihr Bugs findet, dürft ihr sie behal--- ääääh, schreibt mir eine PM oder einen Worklogkommentar. Die Wahrscheinlichkeit ist aber gross, dass der Bug schon bekannt ist.
EDIT: Ihr könnt auch euer Feedback in folgenden Thread eintragen: *KLICK*
- In der IDE ein neues Dokument öffnen, etwas Code schreiben und dann mit F5 kompilieren geht nicht - ihr müsst die Datei zuerst speichern.
- Syntaxfehler werden immer erkannt, aber geben im Moment nur "Syntax error" mit Zeilen- und Spaltenangabe aus; was genau das Problem ist, muss man dann selber herausfinden (am besten durch das Lesen der Sprachspezifikation). Das wird durch das schreiben eines eigenes Parsers in Zukunft behoben, aber auf das kann man sich noch ein wenig gedulden.
- Der Compiler ist im Moment Windows-only. Linux und MacOS-Support kommen zwar irgendwann, aber haben im Moment noch keine Priorität.

Bitte denkt daran, dass das ein mehr-als-Alpha-Release ist. Es soll als Vorgeschmack dienen und nicht als fertiges Produkt Wink

Die nächsten Schritte
Priorität hat im Moment ein auf gdb aufbauender Debugger für Bismuth, um die Sprache auch anständig debuggen zu können. Als nächster Schritt wird der Bismuth-Compiler dann in Bismuth selbst neu geschrieben und dabei auch bisherige Baustellen, Ungereimtheiten und Bugs behoben. Dadurch, dass ich dann selber gezwungen bin, Bismuth zu benutzen, fallen mir hoffentlich selber noch schlechte Designentscheide oder Bugs auf.
Was danach geschieht, ist noch offen - Portieren bestehender BMax-Module, eine bessere IDE mit Autocompletion (da man den Compiler schon mal hat), grösser angelegtes Release - je nach dem wird das Projekt auch eingestampft, weil niemand Interesse daran hat Razz Man ist gespannt.

Vielen Dank fürs Lesen und viel Spass beim Ausprobieren!

Anbei noch ein kleiner Screenshot des in Bismuth geschriebenen Minecraft-Klons namens ZauberCraft (welcher mitunter mal crasht, weil ich noch einen Bug irgendwo stecken habe):
user posted image

Anbei auch noch ein Codebeispiel (Hauptdatei von ZauberCraft): BlitzMax: [AUSKLAPPEN]
Import "TList.bi"

Import "Vector4.bi"

Import "Matrix4.bi"
Import "Matrix4GL.bi"

Import "Entity.bi"

Import "Renderer.bi"
Import "RendererGL.bi"

Import "InputHandler.bi"

Import "Camera.bi"

Import "BufferObject.bi"
Import "VertexBufferGL.bi"
Import "IndexBufferGL.bi"

Import "Texture2D.bi"
Import "Texture2DGL.bi"

Import "Mesh.bi"
Import "MeshGL.bi"

Import "PerlinNoise.bi"
Import "Chunk.bi"
Import "BlockClass.bi"
Import "LuaHandler.bi"
Import "Skybox.bi"

Import "Util.bi"
Import "GLUtil.bi"

Import "Pixmap.bi"

Local Renderer:TRenderer = CreateRenderer()
Renderer.Graphics3D(1024, 768)

Local Camera:TCamera = CreateCamera()
Camera.SetClsColor(64, 64, 64, 255)
Camera.SetRange(1.0, 1000.0)
Renderer.SetCamera(Camera)

Local Player:TPlayer = New TPlayer(Camera)

TLuaHandler.Init()
TBlockClass.Init()
TChunk.Init()

Local Skybox:TSkybox = New TSkybox.Create("Skybox_")

Renderer.Flip()
TInputHandler.GetMouseXSpeed()
TInputHandler.GetMouseYSpeed()

While Not GetKeyHit(KEY_ESCAPE)
TChunk.UpdateChunks()
TChunk.CreateVisibleChunks(Player, 128.0)
Player.Update()
Skybox.Locate(Player.Position.X, Player.Position.Y, Player.Position.Z)

Renderer.RenderWorld()
Renderer.Flip()
Wend
End()

Class TPlayer Extends TEntity
Private
Field Camera:TCamera
Field RotAngle:TVector4
Field RotSpeed:TVector4
Field PosSpeed:TVector4

Field Frame:Int
Public

Method Update()
RotSpeed.X = (RotSpeed.X*5.0 - GetMouseYSpeed()*0.2)/6.0
RotSpeed.Y = (RotSpeed.Y*5.0 + GetMouseXSpeed()*0.2)/6.0
PosSpeed.X = (PosSpeed.X*5.0 + (GetKeyDown(KEY_RIGHT) - GetKeyDown(KEY_LEFT))*0.2)/6.0
PosSpeed.Z = (PosSpeed.Z*5.0 + (GetKeyDown(KEY_DOWN ) - GetKeyDown(KEY_UP ))*0.2)/6.0

RotAngle.Plus(RotSpeed)

Locate(Position.X, Position.Y, Position.Z)

Rotate(RotAngle.X, 0.0, 0.0)
Turn(0.0, RotAngle.Y, 0.0)
Move(PosSpeed.X, 0.0, PosSpeed.Z, False)

If (Frame Mod 30) = 0 Then TInputHandler.MoveMouse(512, 384)
Frame = Frame + 1
End Method

Method Locate(X:Float, Y:Float, Z:Float)
Super .Locate(X, Y, Z)
Camera.Locate(X, Y, Z)
End Method

Method Move(X:Float, Y:Float, Z:Float, F:Int)
Super .Move(X, Y, Z, F)
Camera.Move(X, Y, Z, F)
End Method

Method Rotate(X:Float, Y:Float, Z:Float)
Super .Rotate(X, Y, Z)
Camera.Rotate(X, Y, Z)
End Method

Method Turn(X:Float, Y:Float, Z:Float)
Super .Turn(X, Y, Z)
Camera.Turn(X, Y, Z)
End Method

Method TPlayer(Camera:TCamera)
Super.Create()

Self.Camera = Camera

RotAngle = Vec3(-40.0, 180.0, 0.0)
RotSpeed = Vec3(0.0, 0.0, 0.0)
PosSpeed = Vec3(0.0, 0.0, 0.0)

Locate(240.0, 100.0, 200.0)
End Method
End Class


Ich sollte vielleicht noch anmerken, dass ZauberCraft während der Entwicklung des Bismuth-Compilers organisch mitgewachsen ist. Man findet also sehr viele verschiedene Codestile im Code, die verschiedenen Versionen des Compilers entsprechen - z.B. der aus BMax bekannte Pseudokonstruktor Create nebst echten Konstruktoren etc. Man sollte den Code also nicht als Leitfaden für hübschen Bismuth-Code herbeiziehen Razz