Die Erschaffung einer 3D Welt hat viel mit dem Job eines Film-Regisseurs zutun. Man hat Kameras, Licht, Figuren(=Schauspieler), Szenen, Special Effects, eine Handlung usw. Und du als Regisseur legst fest, wo all diese Dinge sich befinden müssen und wie sie miteinander interagieren. Wenn du denkst, dass das Licht für eine bestimmte Szene etwas bläulicher sein sollte, sagst du dem Licht-Techniker, er soll einen Blau-Filter verwenden. Möchtest du, dass die Kamera den Darsteller von rechts nach links umfliegt, beschreibst du dem Kameramann die genau Kamerafahrt, so wie du sie gerne hättest.
Nun, all diese Dinge müssen in Blitz3D auch gemacht werden! Der einzige unterschied besteht darin, nicht einfach zu sagen "Die Kamera soll an dem Darsteller langsam vorbeifliegen", sondern man muss den Code dafür schreiben.
In diesem Tutorial werden wir die verschiedenen Licht-Typen behandeln. Wie man sie einsetzt, die Farben ändert und sie miteinander mixt um noch mehr Farben zu erhalten. Und wir werden uns anschauen wie man eine Kamera in einer Szene bewegt, was für mich eines der coolsten Dinge in einem 3D Spiel überhaupt ist.
Umgebungsbeleuchtung
Das Wort "Ambient Lighting" (=Umgebugsbeleuchtung) wird benutzt um das Licht, speziell die Farbe des Lichts, der Umgebung zu beschreiben. Hier ist ein einfaches Programm, dass ein rotes Umgebungslicht kreiert.
;Als erstes setzen wir die Auflösung. ;Ich benutze 640x480 hier. GRAPHICS3D 640,480
;Zweitens, genau wie in Blitz2D, benutzen ;wir "Doublebuffering" SETBUFFER BackBuffer()
;Jetzt brauchen wir eine Kamera camera = CREATECAMERA()
;Und wir stellen die Kameara so ein, dass sie auf dem ;ganzen Bildschirm angezeigt wird CAMERAVIEWPORT camera,0,0,GRAPHICSWIDTH(),GRAPHICSHEIGHT()
;Einen Zylinder erstellen, damit wir ;was auf dem Bildschirm haben GLOBAL cylinder=CREATECYLINDER(6)
;Schieben des Zylinders, damit er sichtbar wird MOVEENTITY cylinder,0,0,5
;Schleife bis die "ESC"-Taste gedrückt wird WHILE NOT KEYHIT(1)
;Den Zylinder in alle Richtungen drehen TURNENTITY cylinder,1,1,1
;Die Animationen aktualisieren und ;Kollision abfragen UPDATEWORLD
;Aktuellen Bildschirm rendern RENDERWORLD
;Die Seite "flippen" FLIP
WEND ;Ende der While-Schleife
Wenn man nun das Programm ausführt, sieht man einen sich drehenden roten Zylinder. Es ist Rot, weil es das helle rote Umgebungslicht der Szene reflektiert. Ändere nun die Werte im Befehl AmbientLight um die verschiedenen Farben zu sehen. Der erste Wert ist der Rotanteil, der zweite für den Grünanteil und der dritte für Blau. Die Werte können zwischen 0 und 255 sein, wobei 0 der dunkelste und 255 der hellste Wert ist. Beispiel: 0,0,0 wäre Schwarz und 255,255,255 wäre weis. (0,255,0 = Grün, 0,0,255 = blau usw. Man kann die Farben mischen um dann andere Farben zu erhalten. In einem guten Malprogramm könnt ihr die RGB-Werte beim wählen/ändern einer Farbe ablesen. Anm. v. Konstantin)
Richtungsbeleuchtung
"Directional lighting" (=Richtungsbeleuchtung) ist ein Licht, dass nicht die ganze Szene ausfüllt sondern nur in eine bestimmte Richtung leuchtet. Es beleuchtet nur das, worauf es gerichtet ist. Hier ein Beispiel:
;Als erstes setzen wir die Auflösung. ;Ich benutze 640x480 hier. GRAPHICS3D 640,480
;Zweitens, genau wie in Blitz2D, benutzen ;wir "Doublebuffering" SETBUFFER BACKBUFFER()
;Erstellen eines Lichts mit dem Wert (1), was Blitz3D ;sagt, dass es ein Richtungslicht sein soll light = CREATELIGHT(1)
;Die Farbe des Lichts auf leuchtendes Blau setzen LIGHTCOLOR light,0,0,255
;Jetzt brauchen wir eine Kamera camera = CREATECAMERA()
;Und wir stellen die Kameara so ein, dass sie auf dem ;ganzen Bildschirm angezeigt wird CAMERAVIEWPORT camera,0,0,GRAPHICSWIDTH(),GRAPHICSHEIGHT()
;eipaar Zylinder erstellen, damit wir etwas ;auf dem Bildschirm haben GLOBAL cylinder=CREATECYLINDER(6) GLOBAL cylinder2=CREATECYLINDER(6)
;Schieben der Zylinder nach vorne damit sie sichtbar werden MOVEENTITY cylinder,-7,0,10 MOVEENTITY cylinder2,7,0,10
;Schleife bis die "ESC"-Taste gedrückt wird WHILE NOT KEYHIT(1)
;Drehen des Lichts von rechts nach links ;(gieren=Yaw des lichts) TURNENTITY light,0,-1,0
;Die Animationen aktualisieren und ;Kollision abfragen UPDATEWORLD
;Aktuellen Bildschirm rendern RENDERWORLD
;Die Seite "flippen" FLIP
WEND ;Ende der While-Schleife
Dieses Programm zeigt zwei Zylinder über die ein blaues Licht drüberfegt. Das ist ein Beispiel für Richtungslicht.
Punktbeleuchtung
Wenn man den Licht-Typ "Point" (=Punkt) kreiert, stellt man sich vor es ist wörtlich ein Punkt im Raum von dem aus ein Licht ausgeht. Eine Lichtquelle eben, so wie wenn man eine Lampe in der irgendwo in der Szene platziert. Beispiel:
;Als erstes setzen wir die Auflösung. ;Ich benutze 640x480 hier. GRAPHICS3D 640,480
;Zweitens, genau wie in Blitz2D, benutzen ;wir "Doublebuffering" SETBUFFER BACKBUFFER()
;Eine Lichtquelle erstellen, und den Wert ;(2) für "Point" (=Punkt) einsetzen light = CREATELIGHT(2)
;Die Farbe des Lichts auf Rot setzen LIGHTCOLOR light,0,0,255
;Jetzt brauchen wir eine Kamera camera = CREATECAMERA()
;Und wir stellen die Kameara so ein, dass sie auf dem ;ganzen Bildschirm angezeigt wird CAMERAVIEWPORT camera,0,0,GRAPHICSWIDTH(),GRAPHICSHEIGHT()
;Zwei Zylinder, damit wir etwas auf dem Bild haben GLOBAL cylinder=CREATECYLINDER(6) GLOBAL cylinder2=CREATECYLINDER(6)
;Schieben der Zylinder und des Lichts nach vorne ;damit sie sichtbar werden MOVEENTITY cylinder,0,1.5,5 MOVEENTITY cylinder2,0,-1.5,5 MOVEENTITY light,0,-5,0
;Schleife bis die Taste "ESC" gedrückt wird WHILE NOT KEYHIT(1)
;Die Animationen aktualisieren und ;Kollision abfragen UPDATEWORLD
;Aktuellen Bildschirm rendern RENDERWORLD
;Die Seite "flippen" FLIP
WEND ;Ende der While-Schleife
Der obere Deckel des untersten Zylinders wird nicht vom blauen Licht beleuchtet, weil das Licht sich unter dem Zylinder befindet. Wenn man z.B. die Kamera hinter die Zylinder bewegt, sieht man die Lichtquelle gar nicht, da die Zylinder sie verdecken. (die Kamera wirst du im letzten Beispiel dieses Tutorials bewegen können)
Scheinwerfer-Licht
Der letzte Licht-Typ, den es gibt ist das "Spotlight" (=Scheinwerfer-licht). Wir alle kennen es aus dem realen Leben. Denke einfach an BatMan, da wird sein Zeichen auf den Himmel mit Hilfe eines Scheinwerfers projiziert. Der Lichtstrahl sieht wie ein Kegel aus. Wie das Richtungslicht, kann auch der Scheinwerfer überall in der Szene positioniert, bewegt und mit verschieden gefärbt werden.
Folgendes Beispiel zeigt wo und wie man den Scheinwerfer einsetzen kann.
;Als erstes setzen wir die Auflösung. ;Ich benutze 640x480 hier. GRAPHICS3D 640,480
;Zweitens, genau wie in Blitz2D, benutzen ;wir "Doublebuffering" SETBUFFER BACKBUFFER()
;Die Farbe des Umgebungslichts auf dunkles grün-bla sezten AMBIENTLIGHT(0,55,55)
;Eine Lichtquelle mit dem Wert (3) (=Spotlight) erstellen light = CREATELIGHT(3)
;Die Farbe des Scheinwerferlichts auf ;leuchtendes Rosa setzen LIGHTCOLOR light,255,0,255 ;Anpassen des Winkels des Scheinwerfers bis ;es richtig aussieht LIGHTCONEANGLES light,0,2 ;Positionieren des Lichts auf der -75ten (hinten) ;Einheit der Z-Achse POSITIONENTITY light,0,0,-75 ;Die Reichweite des Scheinwerfers einstellen LIGHTRANGE light,75
;Jetzt brauchen wir eine Kamera camera = CREATECAMERA()
;Und wir stellen die Kamera so ein, dass sie auf dem ;ganzen Bildschirm angezeigt wird CAMERAVIEWPORT camera,0,0,GRAPHICSWIDTH(),GRAPHICSHEIGHT()
;Einpaar Kugeln, damit wir was auf dem Bild haben GLOBAL sphere=CREATESPHERE(12) GLOBAL sphere2=CREATESPHERE(6)
;Die Kugeln nach vorne schieben, damit ;sie sichtbar werden MOVEENTITY sphere,-1.5,0,3 MOVEENTITY sphere2,1.5,0,7
;Variable, die die Richtung unseres ;Scheinwerfers speichert v# = .05
;Schleife bis die "ESC"-Taste gedrückt wird WHILE NOT KEYHIT(1)
;wenn das gieren (Yaw) des Lichts grösser 5 ist ;dann das Scheinwerfer in die andere ;Richtung bewegen. IF ENTITYYAW(light) > 5 THEN v = -.05
;wenn das gieren (Yaw) des kleiner -5 ist ;Das Licht wieder in die andere Richt. bewegen IF ENTITYYAW(light) < -5 THEN v = .05
;Drehen des Lichts um die Y-Achse (gieren/Yaw) TURNENTITY light,0,v,0
;Die Animationen aktualisieren und ;Kollision abfragen UPDATEWORLD
;Aktuellen Bildschirm rendern RENDERWORLD
;Die Seite "flippen" FLIP
WEND ;Ende der While-Schleife
Wenn man dieses Programm startet, sieht man zwei Kugeln. Eine ist näher als die andere. Ein rötliches Scheinwerferlicht bewegt sich langsam vor und zurück über sie hinweg. Für die rechts-links Bewegung des Scheinwerfers ist der Befehl TurnEntity zuständig, der speziell die sogenannte Yaw-bewegung (gieren, drehen um die Y-Achse) nutzt. Aber woher weis das Programm wie weit es nach rechts gehen soll bevor es wieder die Richtung nach Links wechselt? Wir benutzen den EntityYaw Befehl um den aktuellen Yaw-Winkel des Objekts - unseres Scheinwerfers - zu bekommen. Wenn wir die hoch-runter Winkel wollten, würden wir den EntityPitch (dehen des Objekts um die X-Achse) Befehl benutzen. Und für den Roll-Winkel? genau: EntytyRoll (Drehung des Objekts um die Z-Achse.
Wir benutzen auch den AmbientLight Befehl um einen scharfen Kontrast zu dem Scheinwerferlicht zu erreichen.
Es gibt da noch einpaar zusätzliche Befehle, die wir mal behandeln sollten. Als erstes wäre da der LightConeAngles Befehl. Es können drei verschiedene Parameter eingestellt werden. Das erste bedeutet welches Licht benutzt werden soll (wenn man mehrere hat, also den Namen den man einem Licht beim Erstellen zugewiesen hat. Anm. von Konstantin). der Zweite Parameter stellt den inneren Radius des Scheinwerfers ein, und der dritte den Äußeren. Da Scheinwerfer einen Lichtkegel abgeben kann man die beiden Radien verändern. Ich habe etwas rumexperimentiert bis ich die gewünschte Einstellungen hatte. Spiel einfach mit diesen Parametern etwas rum um ein zu sehen was man alles so machen kann.
Der zweite Befehl ist der LightRange. Zwei Parameter können eingegeben werden: "Entity" (=Objekt) und Rechweite. "Entity" ist der Name für das Licht, für welches wir die Reichweite des Lichts einstellen wollen. Diese Einstellungen sind immer sehr variabel, man muss damit rumexperimentieren bis man die richtige Einstellungen hat. Z.B. habe ich das Licht nach hinten um 75 Einheiten bewegt, eine Reichweite von 50 würde aber trotzdem die Objekte (in diesem Fall Kugeln) treffen. Ich habe die Reichweite auf 75 Einheiten gesetzt, weil mir der Effekt besser gefiel. Spiele damit etwas rum und schau was passiert.
Kamerabewegung
Kamerabewegung ist in der Entwicklung von Spielen eine wichtige Sache. Man benutzt Kameras um seine Figur aus verschiedenen Perspektiven zu sehen. Man kann z.B. in einem Speil einen Zauberspruch aussprechen, bei dem man durch fliegende Augen sieht, wodurch man dann um die Ecke schauen kann, ohne seine Figur einem Risiko auszusetzen.
Der folgende Code ist etwas groß, aber er macht einige coole Dinge. Ich erstellte zwei Kegel und ließ sie um sich drehen, damit man mehr zum betrachten hat. Ich fügte zwei zusätzliche Scheinwerfer hinzu. Und schließlich ist da noch die Möglichkeit, die Kamera vor- und rückwärts zu bewegen, nach oben und unten zu schauen oder sich nach rechts oder links zu drehen. Obwohl dieses Beispiel nichts gegen das ist, was Blitz3D noch leisten kann, kannst du dir ein Bild davon machen, wie man sich durch eine Blitz3D-Welt bewegt.
Noch ein Hinweis: Dieser Code wäre normalerweise noch in einpaar Subroutinen unterteilt, aber ich habe es für dieses kleine Demo so gelassen, um es so einfach wie möglich darzustellen. Hier der Code:
;Als erstes setzen wir die Auflösung. ;Ich benutze 640x480 hier. GRAPHICS3D 640,480
;Zweitens, genau wie in Blitz2D, benutzen ;wir "Doublebuffering" SETBUFFER BACKBUFFER()
;Umgebugslicht auf dunkleres grün setzen AMBIENTLIGHT(0,55,55)
;erster Scheinwerfer soll Rosa leuchten LIGHTCOLOR light,255,0,255 ;Die winkel des Lichkegels einstellen LIGHTCONEANGLES light,0,2 ;Position des Scheinwerfers POSITIONENTITY light,0,0,-75 ;Reichweite des Scheinwerfers LIGHTRANGE light,75
;das zweite Licht soll gelb leuchten LIGHTCOLOR light2,255,255,0 ;Die winkel des Lichkegels einstellen LIGHTCONEANGLES light2,0,2 ;Position des Scheinwerfers POSITIONENTITY light2,0,0,-75 ;Reichweite des Scheinwerfers LIGHTRANGE light2,75
;Das dritte Licht soll weis leuchten LIGHTCOLOR light3,255,255,255 ;Die winkel des Lichkegels einstellen LIGHTCONEANGLES light3,0,5 ;Position des Scheinwerfers POSITIONENTITY light3,18,0,-75 ;Reichweite des Scheinwerfers LIGHTRANGE light3,100
;Jetzt brauchen wir eine Kamera camera = CREATECAMERA()
;Und wir stellen die Kameara so ein, dass sie auf dem ;ganzen Bildschirm angezeigt wird CAMERAVIEWPORT camera,0,0,GRAPHICSWIDTH(),GRAPHICSHEIGHT()
;Erstellen einiger Objekte GLOBAL sphere=CREATESPHERE(12) GLOBAL sphere2=CREATESPHERE(6) GLOBAL cone=CREATECONE(24) GLOBAL cone2=CREATECONE(24)
;bewegen der Objekte auf den richtigen Platz MOVEENTITY sphere,-1.5,0,3 MOVEENTITY sphere2,1.5,0,7 MOVEENTITY cone,18,0,30 MOVEENTITY cone2,18,0,20
;Variable, die die Richtung unseres ;Scheinwerfers speichert offSet# = .05
;Schleife bis die "ESC"-Taste gedrückt wird WHILE NOT KEYHIT(1)
;Wenn der Gierwinkel des ersten ;Lichts 5 übersteigt... ;...das Licht wieder in die andere Richtung drehen IF ENTITYYAW(light) > 5 THEN offset = -.08
;Wenn der Gierwinkel des ersten ;Lichts weniger als -17 wird... ;...die Drehrichtung wieder ändern IF ENTITYYAW(light) < -17 THEN offset = .08
;drehen des ersten lichts TURNENTITY light,0,Offset,0
;drehen der Kegel TURNENTITY cone,0,0,1 TURNENTITY cone2,2,2,2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Die rechts-links Bewegung der Kamera abfragen (Yaw) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; beim drücken der Rechts-Taste... IF KEYDOWN(205) THEN ;...die Kamera um die Y-Achse rechts ;drehen (Yaw) camerayaw = -2 ;eine markierung setzen, damit wir die ;Kamera nur bei gerückter taste drehen yawkeyhit = 1 ENDIF
;beim drücken der Links-Taste IF KEYDOWN(203) THEN ;die Kamera um die Y-Achse links ;drehen (Yaw) camerayaw = 2 ;eine Markierung setzen, damit wir die ;Kamera nur bei gedrückter Taste bewegen yawkeyhit = 1 ENDIF
;Wenn YawKeyHit=1 dann ;drehen wir die Kamera um die Y-Achse IF yawkeyhit = 1 THEN ;Die Kameara in die richtige Richtung drehen TURNENTITY camera,0,camerayaw,0 ;Die Markierung zurücksetzen yawkeyhit = 0 ENDIF
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Neigung der Kamera abfragen(Pitch) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IF KEYDOWN(208) THEN ;nach oben schauen camerapitch = -1 ;wieder eine Markierung pitchkeyhit = 1 ENDIF IF KEYDOWN(200) THEN ;nach unten neigen camerapitch = 1 ;Markierung pitchkeyhit = 1 ENDIF
;Wenn PitchKeyHit=1 ;dann neigen wir die Kamera IF pitchkeyhit = 1 ;Neigen der Kamera TURNENTITY camera,camerapitch,0,0 ;Markierung wieder Zurücksetzen pitchkeyhit = 0 ENDIF
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Abfragen der vor- und rückwärts Bewegung ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IF KEYDOWN(44) THEN ;Kamera rückwärt bewegen cameradir# = -.1 ;Markierung dirkeyhit = 1 ENDIF
IF KEYDOWN(30) THEN ;Die Kamera nach vorne bewegen cameradir# = .1 ;Markierung dirkeyhit = 1 ENDIF
;Wenn DirKeyHit=1 ;bewegen der Kamera durch ändern des Z-Wertes IF dirkeyhit = 1 THEN ;bewegen der Kamera in die richtige Richtung MOVEENTITY camera,0,0,cameradir# ;Markierung zurücksetzen dirkeyhit = 0 ENDIF
;Die Animationen aktualisieren und ;Kollision abfragen UPDATEWORLD
;Aktuellen Bildschirm rendern RENDERWORLD
;Tastenbeschreibung hinzufügen TEXT 0,0,"A=vorwärts, Y=Rückwärts" TEXT 0,20,"PfeilTasten=oben/unten/rechts/links" TEXT 0,40,"ESC=Beenden"
;Die Seite "flippen" FLIP
WEND ;Ende der While-Schleife
Es gibt da wirklich nichts im Code was wir nicht schon besprochen hätten. Es ist eine Zusammenfassung der verschiedenen Themen, die wir in diesem Tutorial behandelt haben. Spiele ein bisschen mit den Werten herum und schaue was passiert. Und versuche zur Übung selbst mal eine Routine zuschreiben, die die Kamera rollen lässt. Hier einige Tipps: Du brauchst zwei Tasten, musst die Rollgeschwindigkeit festlegen, die Markierung setzen und den TurnEntity Befehl benutzen um die Kamera zu "rollen".